]> git.lizzy.rs Git - rust.git/commitdiff
Produce instead of pointers
authorOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>
Tue, 16 Jan 2018 08:24:38 +0000 (09:24 +0100)
committerOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>
Thu, 8 Mar 2018 07:08:14 +0000 (08:08 +0100)
80 files changed:
src/libcore/cmp.rs
src/librustc/dep_graph/dep_node.rs
src/librustc/middle/const_val.rs
src/librustc/middle/lang_items.rs
src/librustc/middle/mem_categorization.rs
src/librustc/mir/interpret/value.rs
src/librustc/mir/mod.rs
src/librustc/mir/tcx.rs
src/librustc/mir/visit.rs
src/librustc/ty/context.rs
src/librustc/ty/error.rs
src/librustc/ty/inhabitedness/mod.rs
src/librustc/ty/layout.rs
src/librustc/ty/maps/config.rs
src/librustc/ty/maps/keys.rs
src/librustc/ty/maps/on_disk_cache.rs
src/librustc/ty/mod.rs
src/librustc/ty/relate.rs
src/librustc/ty/structural_impls.rs
src/librustc/ty/util.rs
src/librustc/util/ppaux.rs
src/librustc_const_eval/_match.rs
src/librustc_const_eval/eval.rs
src/librustc_const_eval/pattern.rs
src/librustc_data_structures/stable_hasher.rs
src/librustc_lint/types.rs
src/librustc_metadata/decoder.rs
src/librustc_metadata/encoder.rs
src/librustc_mir/borrow_check/nll/type_check/mod.rs
src/librustc_mir/build/expr/as_rvalue.rs
src/librustc_mir/build/matches/mod.rs
src/librustc_mir/build/matches/test.rs
src/librustc_mir/build/misc.rs
src/librustc_mir/hair/cx/expr.rs
src/librustc_mir/hair/cx/mod.rs
src/librustc_mir/interpret/const_eval.rs
src/librustc_mir/interpret/eval_context.rs
src/librustc_mir/interpret/mod.rs
src/librustc_mir/interpret/operator.rs
src/librustc_mir/interpret/place.rs
src/librustc_mir/interpret/terminator/mod.rs
src/librustc_mir/monomorphize/item.rs
src/librustc_mir/shim.rs
src/librustc_mir/transform/generator.rs
src/librustc_mir/transform/inline.rs
src/librustc_mir/transform/qualify_consts.rs
src/librustc_mir/transform/simplify_branches.rs
src/librustc_mir/util/elaborate_drops.rs
src/librustc_passes/consts.rs
src/librustc_trans/base.rs
src/librustc_trans/debuginfo/metadata.rs
src/librustc_trans/debuginfo/type_names.rs
src/librustc_trans/mir/analyze.rs
src/librustc_trans/mir/block.rs
src/librustc_trans/mir/constant.rs
src/librustc_trans/mir/rvalue.rs
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/op.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/lib.rs
src/test/mir-opt/end_region_2.rs
src/test/mir-opt/end_region_3.rs
src/test/mir-opt/end_region_9.rs
src/test/mir-opt/end_region_cyclic.rs
src/test/mir-opt/issue-38669.rs
src/test/mir-opt/match_false_edges.rs
src/test/mir-opt/nll/region-liveness-basic.rs
src/test/mir-opt/simplify_if.rs
src/test/ui/const-eval-overflow-2.rs
src/test/ui/const-eval-overflow-4.rs
src/test/ui/const-eval/issue-43197.rs
src/test/ui/const-expr-addr-operator.rs
src/test/ui/const-fn-error.rs
src/test/ui/const-fn-error.stderr
src/test/ui/const-len-underflow-separate-spans.rs
src/test/ui/const-pattern-not-const-evaluable.rs
src/test/ui/feature-gate-const-indexing.rs
src/test/ui/issue-38875/issue_38875.rs
src/test/ui/union/union-const-eval.rs

index b98470449827e66a99d13e46e876b4bea2ac247e..6602643dc5106f6101b575b214851777dade3760 100644 (file)
@@ -427,6 +427,7 @@ fn cmp(&self, other: &Reverse<T>) -> Ordering {
 ///     }
 /// }
 /// ```
+#[cfg_attr(not(stage0), lang = "ord")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Ord: Eq + PartialOrd<Self> {
     /// This method returns an `Ordering` between `self` and `other`.
@@ -596,7 +597,8 @@ fn partial_cmp(&self, other: &Ordering) -> Option<Ordering> {
 /// assert_eq!(x < y, true);
 /// assert_eq!(x.lt(&y), true);
 /// ```
-#[lang = "ord"]
+#[cfg_attr(stage0, lang = "ord")]
+#[cfg_attr(not(stage0), lang = "partial_ord")]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented = "can't compare `{Self}` with `{Rhs}`"]
 pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
index ed46296389da4ba4f0ad96d6f5f83d3fca4183fe..15e1d38be695025b4253ab216f319f4be99de903 100644 (file)
@@ -63,6 +63,7 @@
 use hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX};
 use hir::map::DefPathHash;
 use hir::{HirId, ItemLocalId};
+use mir;
 
 use ich::Fingerprint;
 use ty::{TyCtxt, Instance, InstanceDef, ParamEnv, ParamEnvAnd, PolyTraitRef, Ty};
index 589890947cd5aabe02f7145e191151417e3184da..cf322010e05c3a57904c6a635cc0899cbd977d0c 100644 (file)
@@ -14,7 +14,7 @@
 use ty::{self, TyCtxt, layout};
 use ty::subst::Substs;
 use rustc_const_math::*;
-use mir::interpret::Value;
+use mir::interpret::{Value, PrimVal};
 
 use graphviz::IntoCow;
 use errors::DiagnosticBuilder;
@@ -39,7 +39,7 @@ pub enum ConstVal<'tcx> {
     Function(DefId, &'tcx Substs<'tcx>),
     Aggregate(ConstAggregate<'tcx>),
     Unevaluated(DefId, &'tcx Substs<'tcx>),
-    /// A miri value, currently only produced if old ctfe fails, but miri succeeds
+    /// A miri value, currently only produced if --miri is enabled
     Value(Value),
 }
 
@@ -71,12 +71,37 @@ fn decode<D: Decoder>(_: &mut D) -> Result<Self, D::Error> {
 }
 
 impl<'tcx> ConstVal<'tcx> {
-    pub fn to_const_int(&self) -> Option<ConstInt> {
+    pub fn to_u128(&self) -> Option<u128> {
         match *self {
-            ConstVal::Integral(i) => Some(i),
-            ConstVal::Bool(b) => Some(ConstInt::U8(b as u8)),
-            ConstVal::Char(ch) => Some(ConstInt::U32(ch as u32)),
-            _ => None
+            ConstVal::Integral(i) => i.to_u128(),
+            ConstVal::Bool(b) => Some(b as u128),
+            ConstVal::Char(ch) => Some(ch as u32 as u128),
+            ConstVal::Value(Value::ByVal(PrimVal::Bytes(b))) => {
+                Some(b)
+            },
+            _ => None,
+        }
+    }
+    pub fn unwrap_u64(&self) -> u64 {
+        match self.to_u128() {
+            Some(val) => {
+                assert_eq!(val as u64 as u128, val);
+                val as u64
+            },
+            None => bug!("expected constant u64, got {:#?}", self),
+        }
+    }
+    pub fn unwrap_usize<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> ConstUsize {
+        match *self {
+            ConstVal::Integral(ConstInt::Usize(i)) => i,
+            ConstVal::Value(Value::ByVal(PrimVal::Bytes(b))) => {
+                assert_eq!(b as u64 as u128, b);
+                match ConstUsize::new(b as u64, tcx.sess.target.usize_ty) {
+                    Ok(val) => val,
+                    Err(e) => bug!("{:#?} is not a usize {:?}", self, e),
+                }
+            },
+            _ => bug!("expected constant u64, got {:#?}", self),
         }
     }
 }
index 447ce46ee5c5c46415e41411780202aff027ee5b..3b37031cf461452978a78fa6a4760262543b4514 100644 (file)
@@ -280,6 +280,7 @@ pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LanguageItems {
     GeneratorTraitLangItem,          "generator",               gen_trait;
 
     EqTraitLangItem,                 "eq",                      eq_trait;
+    PartialOrdTraitLangItem,         "partial_ord",             partial_ord_trait;
     OrdTraitLangItem,                "ord",                     ord_trait;
 
     // A number of panic-related lang items. The `panic` item corresponds to
index c532427cc9b429add7e040e538dae2b638a7c9b0..1c60ae36cd334354245f1d043737f0c1f117c090 100644 (file)
@@ -913,8 +913,7 @@ pub fn cat_rvalue_node(&self,
 
         // Always promote `[T; 0]` (even when e.g. borrowed mutably).
         let promotable = match expr_ty.sty {
-            ty::TyArray(_, len) if
-                len.val.to_const_int().and_then(|i| i.to_u64()) == Some(0) => true,
+            ty::TyArray(_, len) if len.val.to_u128() == Some(0) => true,
             _ => promotable,
         };
 
index 8d67856c0df8da140309a1bc861666323294d3a4..c00956c0a8570445281d519f9be07352a64d6725 100644 (file)
@@ -1,6 +1,7 @@
 #![allow(unknown_lints)]
 
 use ty::layout::{Align, HasDataLayout};
+use ty;
 
 use super::{EvalResult, MemoryPointer, PointerArithmetic};
 use syntax::ast::FloatTy;
@@ -36,6 +37,15 @@ pub enum Value {
     ByValPair(PrimVal, PrimVal),
 }
 
+impl<'tcx> ty::TypeFoldable<'tcx> for Value {
+    fn super_fold_with<'gcx: 'tcx, F: ty::fold::TypeFolder<'gcx, 'tcx>>(&self, _: &mut F) -> Self {
+        *self
+    }
+    fn super_visit_with<V: ty::fold::TypeVisitor<'tcx>>(&self, _: &mut V) -> bool {
+        false
+    }
+}
+
 /// A wrapper type around `PrimVal` that cannot be turned back into a `PrimVal` accidentally.
 /// This type clears up a few APIs where having a `PrimVal` argument for something that is
 /// potentially an integer pointer or a pointer to an allocation was unclear.
index 4c1b8cb79ed1a45bd3c1bd587e2ff42c9c2405b0..d35cbd0027fb68e41d52da076a82ce1a59bfc93f 100644 (file)
@@ -15,7 +15,7 @@
 use graphviz::IntoCow;
 use middle::const_val::ConstVal;
 use middle::region;
-use rustc_const_math::{ConstUsize, ConstInt, ConstMathErr};
+use rustc_const_math::{ConstUsize, ConstMathErr};
 use rustc_data_structures::sync::{Lrc};
 use rustc_data_structures::indexed_vec::{IndexVec, Idx};
 use rustc_data_structures::control_flow_graph::dominators::{Dominators, dominators};
 use hir::def::CtorKind;
 use hir::def_id::DefId;
 use mir::visit::MirVisitable;
+use mir::interpret::{Value, PrimVal};
 use ty::subst::{Subst, Substs};
 use ty::{self, AdtDef, ClosureSubsts, Region, Ty, TyCtxt, GeneratorInterior};
 use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
+use ty::TypeAndMut;
 use util::ppaux;
 use std::slice;
 use hir::{self, InlineAsm};
@@ -707,7 +709,7 @@ pub enum TerminatorKind<'tcx> {
 
         /// Possible values. The locations to branch to in each case
         /// are found in the corresponding indices from the `targets` vector.
-        values: Cow<'tcx, [ConstInt]>,
+        values: Cow<'tcx, [u128]>,
 
         /// Possible branch sites. The last element of this vector is used
         /// for the otherwise branch, so targets.len() == values.len() + 1
@@ -858,7 +860,7 @@ pub fn unwind_mut(&mut self) -> Option<&mut Option<BasicBlock>> {
 impl<'tcx> TerminatorKind<'tcx> {
     pub fn if_<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, cond: Operand<'tcx>,
                          t: BasicBlock, f: BasicBlock) -> TerminatorKind<'tcx> {
-        static BOOL_SWITCH_FALSE: &'static [ConstInt] = &[ConstInt::U8(0)];
+        static BOOL_SWITCH_FALSE: &'static [u128] = &[0];
         TerminatorKind::SwitchInt {
             discr: cond,
             switch_ty: tcx.types.bool,
@@ -1144,12 +1146,16 @@ pub fn fmt_successor_labels(&self) -> Vec<Cow<'static, str>> {
         match *self {
             Return | Resume | Abort | Unreachable | GeneratorDrop => vec![],
             Goto { .. } => vec!["".into()],
-            SwitchInt { ref values, .. } => {
+            SwitchInt { ref values, switch_ty, .. } => {
                 values.iter()
-                      .map(|const_val| {
-                          let mut buf = String::new();
-                          fmt_const_val(&mut buf, &ConstVal::Integral(*const_val)).unwrap();
-                          buf.into()
+                      .map(|&u| {
+                          let mut s = String::new();
+                          print_miri_value(
+                              Value::ByVal(PrimVal::Bytes(u)),
+                              switch_ty,
+                              &mut s,
+                          ).unwrap();
+                          s.into()
                       })
                       .chain(iter::once(String::from("otherwise").into()))
                       .collect()
@@ -1533,7 +1539,12 @@ pub fn function_handle<'a>(
             ty,
             literal: Literal::Value {
                 value: tcx.mk_const(ty::Const {
-                    val: ConstVal::Function(def_id, substs),
+                    val: if tcx.sess.opts.debugging_opts.miri {
+                        // ZST function type
+                        ConstVal::Value(Value::ByVal(PrimVal::Undef))
+                    } else {
+                        ConstVal::Function(def_id, substs)
+                    },
                     ty
                 })
             },
@@ -1853,7 +1864,7 @@ fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
         match *self {
             Value { value } => {
                 write!(fmt, "const ")?;
-                fmt_const_val(fmt, &value.val)
+                fmt_const_val(fmt, value)
             }
             Promoted { index } => {
                 write!(fmt, "{:?}", index)
@@ -1863,9 +1874,9 @@ fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
 }
 
 /// Write a `ConstVal` in a way closer to the original source code than the `Debug` output.
-fn fmt_const_val<W: Write>(fmt: &mut W, const_val: &ConstVal) -> fmt::Result {
+fn fmt_const_val<W: Write>(fmt: &mut W, const_val: &ty::Const) -> fmt::Result {
     use middle::const_val::ConstVal::*;
-    match *const_val {
+    match const_val.val {
         Float(f) => write!(fmt, "{:?}", f),
         Integral(n) => write!(fmt, "{}", n),
         Str(s) => write!(fmt, "{:?}", s),
@@ -1882,7 +1893,41 @@ fn fmt_const_val<W: Write>(fmt: &mut W, const_val: &ConstVal) -> fmt::Result {
         Function(def_id, _) => write!(fmt, "{}", item_path_str(def_id)),
         Aggregate(_) => bug!("`ConstVal::{:?}` should not be in MIR", const_val),
         Unevaluated(..) => write!(fmt, "{:?}", const_val),
-        Value(val) => write!(fmt, "{:?}", val),
+        Value(val) => print_miri_value(val, const_val.ty, fmt),
+    }
+}
+
+fn print_miri_value<W: Write>(value: Value, ty: Ty, f: &mut W) -> fmt::Result {
+    use ty::TypeVariants::*;
+    use rustc_const_math::ConstFloat;
+    match (value, &ty.sty) {
+        (Value::ByVal(PrimVal::Bytes(0)), &TyBool) => write!(f, "false"),
+        (Value::ByVal(PrimVal::Bytes(1)), &TyBool) => write!(f, "true"),
+        (Value::ByVal(PrimVal::Bytes(bits)), &TyFloat(fty)) =>
+            write!(f, "{}", ConstFloat { bits, ty: fty }),
+        (Value::ByVal(PrimVal::Bytes(n)), &TyUint(ui)) => write!(f, "{:?}{}", n, ui),
+        (Value::ByVal(PrimVal::Bytes(n)), &TyInt(i)) => write!(f, "{:?}{}", n as i128, i),
+        (Value::ByVal(PrimVal::Bytes(n)), &TyChar) =>
+            write!(f, "{:?}", ::std::char::from_u32(n as u32).unwrap()),
+        (Value::ByVal(PrimVal::Undef), &TyFnDef(did, _)) =>
+            write!(f, "{}", item_path_str(did)),
+        (Value::ByValPair(PrimVal::Ptr(ptr), PrimVal::Bytes(len)), &TyRef(_, TypeAndMut {
+            ty: &ty::TyS { sty: TyStr, .. }, ..
+        })) => {
+            ty::tls::with(|tcx| {
+                let alloc = tcx
+                    .interpret_interner
+                    .borrow()
+                    .get_alloc(ptr.alloc_id.0)
+                    .expect("miri alloc not found");
+                assert_eq!(len as usize as u128, len);
+                let slice = &alloc.bytes[(ptr.offset as usize)..][..(len as usize)];
+                let s = ::std::str::from_utf8(slice)
+                    .expect("non utf8 str from miri");
+                write!(f, "{:?}", s)
+            })
+        },
+        _ => write!(f, "{:?}:{}", value, ty),
     }
 }
 
@@ -2468,6 +2513,15 @@ fn super_visit_with<Vs: TypeVisitor<'tcx>>(&self, visitor: &mut Vs) -> bool {
     }
 }
 
+impl<'tcx> TypeFoldable<'tcx> for Field {
+    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, _: &mut F) -> Self {
+        *self
+    }
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> bool {
+        false
+    }
+}
+
 impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> {
     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
         Constant {
index bbfb9c89b3fc4d0e513c08bde9693924209c25bb..067c1742040bfb3b7447d2e0d51e0c569e994909 100644 (file)
@@ -70,7 +70,7 @@ pub fn projection_ty(self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
                 PlaceTy::Ty {
                     ty: match ty.sty {
                         ty::TyArray(inner, size) => {
-                            let size = size.val.to_const_int().unwrap().to_u64().unwrap();
+                            let size = size.val.unwrap_u64();
                             let len = size - (from as u64) - (to as u64);
                             tcx.mk_array(inner, len)
                         }
index 0b6f1275bdb4c64fbfd7de2f8b527abc15160a6f..54d3ed38d65370f163a348b75ab84158d9265d5b 100644 (file)
@@ -243,12 +243,6 @@ fn visit_generator_interior(&mut self,
                 self.super_generator_interior(interior);
             }
 
-            fn visit_const_int(&mut self,
-                               const_int: &ConstInt,
-                               _: Location) {
-                self.super_const_int(const_int);
-            }
-
             fn visit_const_usize(&mut self,
                                  const_usize: & $($mutability)* ConstUsize,
                                  _: Location) {
@@ -426,13 +420,10 @@ fn super_terminator_kind(&mut self,
 
                     TerminatorKind::SwitchInt { ref $($mutability)* discr,
                                                 ref $($mutability)* switch_ty,
-                                                ref values,
+                                                values: _,
                                                 ref targets } => {
                         self.visit_operand(discr, source_location);
                         self.visit_ty(switch_ty, TyContext::Location(source_location));
-                        for value in &values[..] {
-                            self.visit_const_int(value, source_location);
-                        }
                         for &target in targets {
                             self.visit_branch(block, target);
                         }
@@ -798,9 +789,6 @@ fn super_closure_substs(&mut self,
                                     _substs: & $($mutability)* ClosureSubsts<'tcx>) {
             }
 
-            fn super_const_int(&mut self, _const_int: &ConstInt) {
-            }
-
             fn super_const_usize(&mut self, _const_usize: & $($mutability)* ConstUsize) {
             }
 
index 520da34c40acbfbfa005bf18f61dc3c2c22d838a..17926eeec0020033254faa17729649c322de0845 100644 (file)
@@ -30,7 +30,8 @@
 use middle::lang_items;
 use middle::resolve_lifetime::{self, ObjectLifetimeDefault};
 use middle::stability;
-use mir::{Mir, interpret};
+use mir::{self, Mir, interpret};
+use mir::interpret::{Value, PrimVal};
 use ty::subst::{Kind, Substs};
 use ty::ReprOptions;
 use ty::Instance;
@@ -1267,6 +1268,36 @@ pub fn lang_items(self) -> Lrc<middle::lang_items::LanguageItems> {
         self.get_lang_items(LOCAL_CRATE)
     }
 
+    pub fn is_binop_lang_item(&self, def_id: DefId) -> Option<(mir::BinOp, bool)> {
+        let items = self.lang_items();
+        let def_id = Some(def_id);
+        if items.i128_add_fn() == def_id { Some((mir::BinOp::Add, false)) }
+        else if items.u128_add_fn() == def_id { Some((mir::BinOp::Add, false)) }
+        else if items.i128_sub_fn() == def_id { Some((mir::BinOp::Sub, false)) }
+        else if items.u128_sub_fn() == def_id { Some((mir::BinOp::Sub, false)) }
+        else if items.i128_mul_fn() == def_id { Some((mir::BinOp::Mul, false)) }
+        else if items.u128_mul_fn() == def_id { Some((mir::BinOp::Mul, false)) }
+        else if items.i128_div_fn() == def_id { Some((mir::BinOp::Div, false)) }
+        else if items.u128_div_fn() == def_id { Some((mir::BinOp::Div, false)) }
+        else if items.i128_rem_fn() == def_id { Some((mir::BinOp::Rem, false)) }
+        else if items.u128_rem_fn() == def_id { Some((mir::BinOp::Rem, false)) }
+        else if items.i128_shl_fn() == def_id { Some((mir::BinOp::Shl, false)) }
+        else if items.u128_shl_fn() == def_id { Some((mir::BinOp::Shl, false)) }
+        else if items.i128_shr_fn() == def_id { Some((mir::BinOp::Shr, false)) }
+        else if items.u128_shr_fn() == def_id { Some((mir::BinOp::Shr, false)) }
+        else if items.i128_addo_fn() == def_id { Some((mir::BinOp::Add, true)) }
+        else if items.u128_addo_fn() == def_id { Some((mir::BinOp::Add, true)) }
+        else if items.i128_subo_fn() == def_id { Some((mir::BinOp::Sub, true)) }
+        else if items.u128_subo_fn() == def_id { Some((mir::BinOp::Sub, true)) }
+        else if items.i128_mulo_fn() == def_id { Some((mir::BinOp::Mul, true)) }
+        else if items.u128_mulo_fn() == def_id { Some((mir::BinOp::Mul, true)) }
+        else if items.i128_shlo_fn() == def_id { Some((mir::BinOp::Shl, true)) }
+        else if items.u128_shlo_fn() == def_id { Some((mir::BinOp::Shl, true)) }
+        else if items.i128_shro_fn() == def_id { Some((mir::BinOp::Shr, true)) }
+        else if items.u128_shro_fn() == def_id { Some((mir::BinOp::Shr, true)) }
+        else { None }
+    }
+
     pub fn stability(self) -> Lrc<stability::Index<'tcx>> {
         self.stability_index(LOCAL_CRATE)
     }
@@ -2068,7 +2099,11 @@ pub fn mk_array(self, ty: Ty<'tcx>, n: u64) -> Ty<'tcx> {
 
     pub fn mk_array_const_usize(self, ty: Ty<'tcx>, n: ConstUsize) -> Ty<'tcx> {
         self.mk_ty(TyArray(ty, self.mk_const(ty::Const {
-            val: ConstVal::Integral(ConstInt::Usize(n)),
+            val: if self.sess.opts.debugging_opts.miri {
+                ConstVal::Value(Value::ByVal(PrimVal::Bytes(n.as_u64().into())))
+            } else {
+                ConstVal::Integral(ConstInt::Usize(n))
+            },
             ty: self.types.usize
         })))
     }
index be89aeebdea756445c2bfb4f296e9e9d206d55ac..07920c58271cd63dc135762dfcb731271a44c5a2 100644 (file)
@@ -11,6 +11,7 @@
 use hir::def_id::DefId;
 use middle::const_val::ConstVal;
 use ty::{self, BoundRegion, Region, Ty, TyCtxt};
+use mir::interpret::{Value, PrimVal};
 
 use std::fmt;
 use syntax::abi;
@@ -186,10 +187,12 @@ pub fn sort_string(&self, tcx: TyCtxt<'a, 'gcx, 'lcx>) -> String {
             ty::TyAdt(def, _) => format!("{} `{}`", def.descr(), tcx.item_path_str(def.did)),
             ty::TyForeign(def_id) => format!("extern type `{}`", tcx.item_path_str(def_id)),
             ty::TyArray(_, n) => {
-                if let ConstVal::Integral(ConstInt::Usize(n)) = n.val {
-                    format!("array of {} elements", n)
-                } else {
-                    "array".to_string()
+                match n.val {
+                    ConstVal::Integral(ConstInt::Usize(n)) =>
+                        format!("array of {} elements", n),
+                    ConstVal::Value(Value::ByVal(PrimVal::Bytes(n))) =>
+                        format!("array of {} elements", n),
+                    _ => "array".to_string(),
                 }
             }
             ty::TySlice(_) => "slice".to_string(),
index 93e4cd9adf888ded465ec92d45730c065e59f234..bfaa661b2432d1f349f38f7622c6d62eb1445ab1 100644 (file)
@@ -262,7 +262,7 @@ fn uninhabited_from(
                 }))
             },
             TyArray(ty, len) => {
-                match len.val.to_const_int().and_then(|i| i.to_u64()) {
+                match len.val.to_u128() {
                     // If the array is definitely non-empty, it's uninhabited if
                     // the type of its elements is uninhabited.
                     Some(n) if n != 0 => ty.uninhabited_from(visited, tcx),
index 1aa7f671ad391a17e5fe57931609719536af4e59..35d8fb2a67ac975d3fd400cb89418ee8aa5bfeb7 100644 (file)
@@ -952,7 +952,7 @@ fn layout_raw_uncached(self, ty: Ty<'tcx>)
         enum StructKind {
             /// A tuple, closure, or univariant which cannot be coerced to unsized.
             AlwaysSized,
-            /// A univariant, the last field of which may be coerced to unsized.
+            /// A univariant, the last field of which fn compute_uncachedmay be coerced to unsized.
             MaybeUnsized,
             /// A univariant, but with a prefix of an arbitrary size & alignment (e.g. enum tag).
             Prefixed(Size, Align),
@@ -1237,7 +1237,7 @@ enum StructKind {
                 }
 
                 let element = self.layout_of(element)?;
-                let count = count.val.to_const_int().unwrap().to_u64().unwrap();
+                let count = count.val.unwrap_u64();
                 let size = element.size.checked_mul(count, dl)
                     .ok_or(LayoutError::SizeOverflow(ty))?;
 
index d880b022e2f18c90c981882b70a6b79d69bac763..ef1c8a8d4fa44e85ec777153d6be0dffb2322bec 100644 (file)
@@ -13,6 +13,7 @@
 use ty::{self, Ty, TyCtxt};
 use ty::maps::queries;
 use ty::subst::Substs;
+use mir;
 
 use std::hash::Hash;
 use syntax_pos::symbol::InternedString;
index b7b64c9761a8e091eceb964b95fc16f88f0a23c1..3dd482ad1640108d2e4620f9b5d69e526a0a7eb5 100644 (file)
@@ -14,6 +14,7 @@
 use ty::{self, Ty, TyCtxt};
 use ty::subst::Substs;
 use ty::fast_reject::SimplifiedType;
+use mir;
 
 use std::fmt::Debug;
 use std::hash::Hash;
index b18837ff35aa81b86348e3b47567b0e38c68bea3..77e022fe7300394a9b2d83cd58f14910595fd746 100644 (file)
@@ -15,7 +15,7 @@
                   RESERVED_FOR_INCR_COMP_CACHE, LOCAL_CRATE};
 use hir::map::definitions::DefPathHash;
 use ich::{CachingCodemapView, Fingerprint};
-use mir;
+use mir::{self, interpret};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::Lrc;
 use rustc_data_structures::indexed_vec::{IndexVec, Idx};
@@ -542,6 +542,13 @@ fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum {
 
 implement_ty_decoder!( CacheDecoder<'a, 'tcx, 'x> );
 
+
+impl<'a, 'tcx, 'x> SpecializedDecoder<interpret::AllocId> for CacheDecoder<'a, 'tcx, 'x> {
+    fn specialized_decode(&mut self) -> Result<interpret::AllocId, Self::Error> {
+        unimplemented!()
+    }
+}
+
 impl<'a, 'tcx, 'x> SpecializedDecoder<Span> for CacheDecoder<'a, 'tcx, 'x> {
     fn specialized_decode(&mut self) -> Result<Span, Self::Error> {
         let tag: u8 = Decodable::decode(self)?;
index be27e3d51529bca6abf0cdcffea20c834d5e1c52..1577e78d81e22e273e4da5c102f9d722cca4077e 100644 (file)
@@ -26,6 +26,7 @@
 use middle::privacy::AccessLevels;
 use middle::resolve_lifetime::ObjectLifetimeDefault;
 use mir::Mir;
+use mir::interpret::{Value, PrimVal};
 use mir::GeneratorLayout;
 use session::CrateDisambiguator;
 use traits;
@@ -1838,6 +1839,19 @@ pub fn discriminants(&'a self, tcx: TyCtxt<'a, 'gcx, 'tcx>)
                     Ok(&ty::Const { val: ConstVal::Integral(v), .. }) => {
                         discr = v;
                     }
+                    Ok(&ty::Const {
+                        val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(b))),
+                        ..
+                    }) => {
+                        trace!("discriminants: {} ({:?})", b, repr_type);
+                        use syntax::attr::IntType;
+                        discr = match repr_type {
+                            IntType::SignedInt(int_type) => ConstInt::new_signed(
+                                b as i128, int_type, tcx.sess.target.isize_ty).unwrap(),
+                            IntType::UnsignedInt(uint_type) => ConstInt::new_unsigned(
+                                b, uint_type, tcx.sess.target.usize_ty).unwrap(),
+                        };
+                    }
                     err => {
                         if !expr_did.is_local() {
                             span_bug!(tcx.def_span(expr_did),
@@ -1879,6 +1893,20 @@ pub fn discriminant_for_variant(&self,
                             explicit_value = v;
                             break;
                         }
+                        Ok(&ty::Const {
+                            val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(b))),
+                            ..
+                        }) => {
+                            trace!("discriminants: {} ({:?})", b, repr_type);
+                            use syntax::attr::IntType;
+                            explicit_value = match repr_type {
+                                IntType::SignedInt(int_type) => ConstInt::new_signed(
+                                    b as i128, int_type, tcx.sess.target.isize_ty).unwrap(),
+                                IntType::UnsignedInt(uint_type) => ConstInt::new_unsigned(
+                                    b, uint_type, tcx.sess.target.usize_ty).unwrap(),
+                            };
+                            break;
+                        }
                         err => {
                             if !expr_did.is_local() {
                                 span_bug!(tcx.def_span(expr_did),
index b9927c7eeb2fa491569db9a92557df892948e4fe..bac78508993a5c1dca48b8d8c8b99df9d19dbe51 100644 (file)
@@ -20,6 +20,7 @@
 use ty::{self, Ty, TyCtxt, TypeFoldable};
 use ty::fold::{TypeVisitor, TypeFolder};
 use ty::error::{ExpectedFound, TypeError};
+use mir::interpret::{Value, PrimVal};
 use util::common::ErrorReported;
 use std::rc::Rc;
 use std::iter;
@@ -483,6 +484,7 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
             let to_u64 = |x: &'tcx ty::Const<'tcx>| -> Result<u64, ErrorReported> {
                 match x.val {
                     ConstVal::Integral(x) => Ok(x.to_u64().unwrap()),
+                    ConstVal::Value(Value::ByVal(prim)) => Ok(prim.to_u64().unwrap()),
                     ConstVal::Unevaluated(def_id, substs) => {
                         // FIXME(eddyb) get the right param_env.
                         let param_env = ty::ParamEnv::empty(Reveal::UserFacing);
@@ -492,6 +494,13 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
                                     Ok(&ty::Const { val: ConstVal::Integral(x), .. }) => {
                                         return Ok(x.to_u64().unwrap());
                                     }
+                                    Ok(&ty::Const {
+                                        val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(b))),
+                                        ..
+                                    }) => {
+                                        assert_eq!(b as u64 as u128, b);
+                                        return Ok(b as u64);
+                                    }
                                     _ => {}
                                 }
                             }
index 54db2d4f06be5485d4bba95ced1bdf53d516e83d..80250949b0b4af64985ed8652b4bc8f3f0d94e3e 100644 (file)
@@ -890,6 +890,61 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
     }
 }
 
+impl<'tcx> TypeFoldable<'tcx> for ty::instance::Instance<'tcx> {
+    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
+        use ty::InstanceDef::*;
+        Self {
+            substs: self.substs.fold_with(folder),
+            def: match self.def {
+                Item(did) => Item(did.fold_with(folder)),
+                Intrinsic(did) => Intrinsic(did.fold_with(folder)),
+                FnPtrShim(did, ty) => FnPtrShim(
+                    did.fold_with(folder),
+                    ty.fold_with(folder),
+                ),
+                Virtual(did, i) => Virtual(
+                    did.fold_with(folder),
+                    i,
+                ),
+                ClosureOnceShim { call_once } => ClosureOnceShim {
+                    call_once: call_once.fold_with(folder),
+                },
+                DropGlue(did, ty) => DropGlue(
+                    did.fold_with(folder),
+                    ty.fold_with(folder),
+                ),
+                CloneShim(did, ty) => CloneShim(
+                    did.fold_with(folder),
+                    ty.fold_with(folder),
+                ),
+            },
+        }
+    }
+
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+        use ty::InstanceDef::*;
+        self.substs.visit_with(visitor) ||
+        match self.def {
+            Item(did) => did.visit_with(visitor),
+            Intrinsic(did) => did.visit_with(visitor),
+            FnPtrShim(did, ty) => {
+                did.visit_with(visitor) ||
+                ty.visit_with(visitor)
+            },
+            Virtual(did, _) => did.visit_with(visitor),
+            ClosureOnceShim { call_once } => call_once.visit_with(visitor),
+            DropGlue(did, ty) => {
+                did.visit_with(visitor) ||
+                ty.visit_with(visitor)
+            },
+            CloneShim(did, ty) => {
+                did.visit_with(visitor) ||
+                ty.visit_with(visitor)
+            },
+        }
+    }
+}
+
 impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
         let sty = match self.sty {
index 785035ee5f4f0d9a852a4e3608b1bf4853e6bb68..6ad2901ce3a100210e13ae67c0b96192dd0d5830 100644 (file)
@@ -24,6 +24,7 @@
 use ty::TypeVariants::*;
 use util::common::ErrorReported;
 use middle::lang_items;
+use mir::interpret::{Value, PrimVal};
 
 use rustc_const_math::{ConstInt, ConstIsize, ConstUsize};
 use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult,
@@ -765,6 +766,7 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
                 self.hash_discriminant_u8(&n.val);
                 match n.val {
                     ConstVal::Integral(x) => self.hash(x.to_u64().unwrap()),
+                    ConstVal::Value(Value::ByVal(PrimVal::Bytes(b))) => self.hash(b),
                     ConstVal::Unevaluated(def_id, _) => self.def_id(def_id),
                     _ => bug!("arrays should not have {:?} as length", n)
                 }
index a2620da4c10ca1d98cefc1ae40d0353a1bfc9635..63d1f1468251b219dd87d2a04190d1f93e8c3a52 100644 (file)
@@ -21,6 +21,7 @@
 use ty::{TyDynamic, TyInt, TyUint, TyInfer};
 use ty::{self, Ty, TyCtxt, TypeFoldable};
 use util::nodemap::FxHashSet;
+use mir::interpret::{Value, PrimVal};
 
 use std::cell::Cell;
 use std::fmt;
@@ -1168,6 +1169,9 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                         ConstVal::Integral(ConstInt::Usize(sz)) => {
                             write!(f, "{}", sz)?;
                         }
+                        ConstVal::Value(Value::ByVal(PrimVal::Bytes(sz))) => {
+                            write!(f, "{}", sz)?;
+                        }
                         ConstVal::Unevaluated(_def_id, substs) => {
                             write!(f, "<unevaluated{:?}>", &substs[..])?;
                         }
index 8e3b99f2dbfee86a13c3007ff5e18877ce50fa76..9e9eb4a81d035d4a06779589a597e6d682da5427 100644 (file)
@@ -28,6 +28,7 @@
 use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
 
 use rustc::mir::Field;
+use rustc::mir::interpret::{Value, PrimVal};
 use rustc::util::common::ErrorReported;
 
 use syntax_pos::{Span, DUMMY_SP};
@@ -195,6 +196,41 @@ fn lower_byte_str_pattern<'p>(&mut self, pat: &'p Pattern<'tcx>) -> Vec<&'p Patt
                         }
                     })).collect()
                 }
+                box PatternKind::Constant {
+                    value: &ty::Const { val: ConstVal::Value(b), ty }
+                } => {
+                    match b {
+                        Value::ByVal(PrimVal::Ptr(ptr)) => {
+                            let is_array_ptr = ty
+                                .builtin_deref(true, ty::NoPreference)
+                                .and_then(|t| t.ty.builtin_index())
+                                .map_or(false, |t| t == tcx.types.u8);
+                            assert!(is_array_ptr);
+                            let alloc = tcx
+                                .interpret_interner
+                                .borrow()
+                                .get_alloc(ptr.alloc_id.0)
+                                .unwrap();
+                            assert_eq!(ptr.offset, 0);
+                            // FIXME: check length
+                            alloc.bytes.iter().map(|b| {
+                                &*pattern_arena.alloc(Pattern {
+                                    ty: tcx.types.u8,
+                                    span: pat.span,
+                                    kind: box PatternKind::Constant {
+                                        value: tcx.mk_const(ty::Const {
+                                            val: ConstVal::Value(Value::ByVal(
+                                                PrimVal::Bytes(*b as u128),
+                                            )),
+                                            ty: tcx.types.u8
+                                        })
+                                    }
+                                })
+                            }).collect()
+                        },
+                        _ => bug!("not a byte str: {:?}", b),
+                    }
+                }
                 _ => span_bug!(pat.span, "unexpected byte array pattern {:?}", pat)
             }
         }).clone()
@@ -422,13 +458,17 @@ fn all_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
         ty::TyBool => {
             [true, false].iter().map(|&b| {
                 ConstantValue(cx.tcx.mk_const(ty::Const {
-                    val: ConstVal::Bool(b),
+                    val: if cx.tcx.sess.opts.debugging_opts.miri {
+                        ConstVal::Value(Value::ByVal(PrimVal::Bytes(b as u128)))
+                    } else {
+                        ConstVal::Bool(b)
+                    },
                     ty: cx.tcx.types.bool
                 }))
             }).collect()
         }
-        ty::TyArray(ref sub_ty, len) if len.val.to_const_int().is_some() => {
-            let len = len.val.to_const_int().unwrap().to_u64().unwrap();
+        ty::TyArray(ref sub_ty, len) if len.val.to_u128().is_some() => {
+            let len = len.val.unwrap_u64();
             if len != 0 && cx.is_uninhabited(sub_ty) {
                 vec![]
             } else {
@@ -461,7 +501,7 @@ fn all_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
 }
 
 fn max_slice_length<'p, 'a: 'p, 'tcx: 'a, I>(
-    _cx: &mut MatchCheckCtxt<'a, 'tcx>,
+    cx: &mut MatchCheckCtxt<'a, 'tcx>,
     patterns: I) -> u64
     where I: Iterator<Item=&'p Pattern<'tcx>>
 {
@@ -538,6 +578,25 @@ fn max_slice_length<'p, 'a: 'p, 'tcx: 'a, I>(
             PatternKind::Constant { value: &ty::Const { val: ConstVal::ByteStr(b), .. } } => {
                 max_fixed_len = cmp::max(max_fixed_len, b.data.len() as u64);
             }
+            PatternKind::Constant {
+                value: &ty::Const {
+                    val: ConstVal::Value(Value::ByVal(PrimVal::Ptr(ptr))),
+                    ty,
+                }
+            } => {
+                let is_array_ptr = ty
+                    .builtin_deref(true, ty::NoPreference)
+                    .and_then(|t| t.ty.builtin_index())
+                    .map_or(false, |t| t == cx.tcx.types.u8);
+                if is_array_ptr {
+                    let alloc = cx.tcx
+                        .interpret_interner
+                        .borrow()
+                        .get_alloc(ptr.alloc_id.0)
+                        .unwrap();
+                    max_fixed_len = cmp::max(max_fixed_len, alloc.bytes.len() as u64);
+                }
+            }
             PatternKind::Slice { ref prefix, slice: None, ref suffix } => {
                 let fixed_len = prefix.len() as u64 + suffix.len() as u64;
                 max_fixed_len = cmp::max(max_fixed_len, fixed_len);
@@ -581,7 +640,7 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
                                        witness: WitnessPreference)
                                        -> Usefulness<'tcx> {
     let &Matrix(ref rows) = matrix;
-    debug!("is_useful({:?}, {:?})", matrix, v);
+    debug!("is_useful({:#?}, {:#?})", matrix, v);
 
     // The base case. We are pattern-matching on () and the return value is
     // based on whether our matrix has a row or not.
@@ -626,10 +685,10 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
         max_slice_length: max_slice_length(cx, rows.iter().map(|r| r[0]).chain(Some(v[0])))
     };
 
-    debug!("is_useful_expand_first_col: pcx={:?}, expanding {:?}", pcx, v[0]);
+    debug!("is_useful_expand_first_col: pcx={:#?}, expanding {:#?}", pcx, v[0]);
 
     if let Some(constructors) = pat_constructors(cx, v[0], pcx) {
-        debug!("is_useful - expanding constructors: {:?}", constructors);
+        debug!("is_useful - expanding constructors: {:#?}", constructors);
         constructors.into_iter().map(|c|
             is_useful_specialized(cx, matrix, v, c.clone(), pcx.ty, witness)
         ).find(|result| result.is_useful()).unwrap_or(NotUseful)
@@ -639,9 +698,9 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
         let used_ctors: Vec<Constructor> = rows.iter().flat_map(|row| {
             pat_constructors(cx, row[0], pcx).unwrap_or(vec![])
         }).collect();
-        debug!("used_ctors = {:?}", used_ctors);
+        debug!("used_ctors = {:#?}", used_ctors);
         let all_ctors = all_constructors(cx, pcx);
-        debug!("all_ctors = {:?}", all_ctors);
+        debug!("all_ctors = {:#?}", all_ctors);
         let missing_ctors: Vec<Constructor> = all_ctors.iter().filter(|c| {
             !used_ctors.contains(*c)
         }).cloned().collect();
@@ -669,7 +728,7 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
             all_ctors.is_empty() && !cx.is_uninhabited(pcx.ty);
         let is_declared_nonexhaustive =
             cx.is_non_exhaustive_enum(pcx.ty) && !cx.is_local(pcx.ty);
-        debug!("missing_ctors={:?} is_privately_empty={:?} is_declared_nonexhaustive={:?}",
+        debug!("missing_ctors={:#?} is_privately_empty={:#?} is_declared_nonexhaustive={:#?}",
                missing_ctors, is_privately_empty, is_declared_nonexhaustive);
 
         // For privately empty and non-exhaustive enums, we work as if there were an "extra"
@@ -769,7 +828,7 @@ fn is_useful_specialized<'p, 'a:'p, 'tcx: 'a>(
     lty: Ty<'tcx>,
     witness: WitnessPreference) -> Usefulness<'tcx>
 {
-    debug!("is_useful_specialized({:?}, {:?}, {:?})", v, ctor, lty);
+    debug!("is_useful_specialized({:#?}, {:#?}, {:?})", v, ctor, lty);
     let sub_pat_tys = constructor_sub_pattern_tys(cx, &ctor, lty);
     let wild_patterns_owned: Vec<_> = sub_pat_tys.iter().map(|ty| {
         Pattern {
@@ -821,7 +880,7 @@ fn pat_constructors<'tcx>(_cx: &mut MatchCheckCtxt,
             Some(vec![ConstantRange(lo, hi, end)]),
         PatternKind::Array { .. } => match pcx.ty.sty {
             ty::TyArray(_, length) => Some(vec![
-                Slice(length.val.to_const_int().unwrap().to_u64().unwrap())
+                Slice(length.val.unwrap_u64())
             ]),
             _ => span_bug!(pat.span, "bad ty {:?} for array pattern", pcx.ty)
         },
@@ -842,7 +901,7 @@ fn pat_constructors<'tcx>(_cx: &mut MatchCheckCtxt,
 /// For instance, a tuple pattern (_, 42, Some([])) has the arity of 3.
 /// A struct pattern's arity is the number of fields it contains, etc.
 fn constructor_arity(_cx: &MatchCheckCtxt, ctor: &Constructor, ty: Ty) -> u64 {
-    debug!("constructor_arity({:?}, {:?})", ctor, ty);
+    debug!("constructor_arity({:#?}, {:?})", ctor, ty);
     match ty.sty {
         ty::TyTuple(ref fs, _) => fs.len() as u64,
         ty::TySlice(..) | ty::TyArray(..) => match *ctor {
@@ -866,12 +925,13 @@ fn constructor_sub_pattern_tys<'a, 'tcx: 'a>(cx: &MatchCheckCtxt<'a, 'tcx>,
                                              ctor: &Constructor,
                                              ty: Ty<'tcx>) -> Vec<Ty<'tcx>>
 {
-    debug!("constructor_sub_pattern_tys({:?}, {:?})", ctor, ty);
+    debug!("constructor_sub_pattern_tys({:#?}, {:?})", ctor, ty);
     match ty.sty {
         ty::TyTuple(ref fs, _) => fs.into_iter().map(|t| *t).collect(),
         ty::TySlice(ty) | ty::TyArray(ty, _) => match *ctor {
             Slice(length) => (0..length).map(|_| ty).collect(),
             ConstantValue(_) => vec![],
+            Single => vec![ty],
             _ => bug!("bad slice pattern {:?} {:?}", ctor, ty)
         },
         ty::TyRef(_, ref ty_and_mut) => vec![ty_and_mut.ty],
@@ -880,6 +940,9 @@ fn constructor_sub_pattern_tys<'a, 'tcx: 'a>(cx: &MatchCheckCtxt<'a, 'tcx>,
                 // Use T as the sub pattern type of Box<T>.
                 vec![substs.type_at(0)]
             } else {
+                if let ConstantValue(_) = *ctor {
+                    return vec![];
+                }
                 adt.variants[ctor.variant_index_for_adt(adt)].fields.iter().map(|field| {
                     let is_visible = adt.is_enum()
                         || field.vis.is_accessible_from(cx.module, cx.tcx);
@@ -901,14 +964,30 @@ fn constructor_sub_pattern_tys<'a, 'tcx: 'a>(cx: &MatchCheckCtxt<'a, 'tcx>,
     }
 }
 
-fn slice_pat_covered_by_constructor(_tcx: TyCtxt, _span: Span,
+fn slice_pat_covered_by_constructor(tcx: TyCtxt, _span: Span,
                                     ctor: &Constructor,
                                     prefix: &[Pattern],
                                     slice: &Option<Pattern>,
                                     suffix: &[Pattern])
                                     -> Result<bool, ErrorReported> {
-    let data = match *ctor {
+    let data: &[u8] = match *ctor {
         ConstantValue(&ty::Const { val: ConstVal::ByteStr(b), .. }) => b.data,
+        ConstantValue(&ty::Const { val: ConstVal::Value(
+            Value::ByVal(PrimVal::Ptr(ptr))
+        ), ty }) => {
+            let is_array_ptr = ty
+                .builtin_deref(true, ty::NoPreference)
+                .and_then(|t| t.ty.builtin_index())
+                .map_or(false, |t| t == tcx.types.u8);
+            assert!(is_array_ptr);
+            tcx
+                .interpret_interner
+                .borrow()
+                .get_alloc(ptr.alloc_id.0)
+                .unwrap()
+                .bytes
+                .as_ref()
+        }
         _ => bug!()
     };
 
@@ -928,6 +1007,12 @@ fn slice_pat_covered_by_constructor(_tcx: TyCtxt, _span: Span,
                         return Ok(false);
                     }
                 },
+                ConstVal::Value(Value::ByVal(PrimVal::Bytes(b))) => {
+                    assert_eq!(b as u8 as u128, b);
+                    if b as u8 != *ch {
+                        return Ok(false);
+                    }
+                }
                 _ => span_bug!(pat.span, "bad const u8 {:?}", value)
             },
             _ => {}
@@ -937,32 +1022,43 @@ fn slice_pat_covered_by_constructor(_tcx: TyCtxt, _span: Span,
     Ok(true)
 }
 
-fn constructor_covered_by_range(tcx: TyCtxt, span: Span,
-                                ctor: &Constructor,
+fn constructor_covered_by_range(ctor: &Constructor,
                                 from: &ConstVal, to: &ConstVal,
-                                end: RangeEnd)
+                                end: RangeEnd,
+                                ty: Ty)
                                 -> Result<bool, ErrorReported> {
-    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);
+    trace!("constructor_covered_by_range {:#?}, {:#?}, {:#?}, {}", ctor, from, to, ty);
+    let cmp_from = |c_from| compare_const_vals(c_from, from, ty)
+        .map(|res| res != Ordering::Less);
+    let cmp_to = |c_to| compare_const_vals(c_to, to, ty);
+    macro_rules! some_or_ok {
+        ($e:expr) => {
+            match $e {
+                Some(to) => to,
+                None => return Ok(false), // not char or int
+            }
+        };
+    }
     match *ctor {
         ConstantValue(value) => {
-            let to = cmp_to(&value.val)?;
+            let to = some_or_ok!(cmp_to(&value.val));
             let end = (to == Ordering::Less) ||
                       (end == RangeEnd::Included && to == Ordering::Equal);
-            Ok(cmp_from(&value.val)? && end)
+            Ok(some_or_ok!(cmp_from(&value.val)) && end)
         },
         ConstantRange(from, to, RangeEnd::Included) => {
-            let to = cmp_to(&to.val)?;
+            let to = some_or_ok!(cmp_to(&to.val));
             let end = (to == Ordering::Less) ||
                       (end == RangeEnd::Included && to == Ordering::Equal);
-            Ok(cmp_from(&from.val)? && end)
+            Ok(some_or_ok!(cmp_from(&from.val)) && end)
         },
         ConstantRange(from, to, RangeEnd::Excluded) => {
-            let to = cmp_to(&to.val)?;
+            let to = some_or_ok!(cmp_to(&to.val));
             let end = (to == Ordering::Less) ||
                       (end == RangeEnd::Excluded && to == Ordering::Equal);
-            Ok(cmp_from(&from.val)? && end)
+            Ok(some_or_ok!(cmp_from(&from.val)) && end)
         }
+        Variant(_) |
         Single => Ok(true),
         _ => bug!(),
     }
@@ -979,7 +1075,7 @@ fn patterns_for_variant<'p, 'a: 'p, 'tcx: 'a>(
         result[subpat.field.index()] = &subpat.pattern;
     }
 
-    debug!("patterns_for_variant({:?}, {:?}) = {:?}", subpatterns, wild_patterns, result);
+    debug!("patterns_for_variant({:#?}, {:#?}) = {:#?}", subpatterns, wild_patterns, result);
     result
 }
 
@@ -994,7 +1090,7 @@ fn patterns_for_variant<'p, 'a: 'p, 'tcx: 'a>(
 fn specialize<'p, 'a: 'p, 'tcx: 'a>(
     cx: &mut MatchCheckCtxt<'a, 'tcx>,
     r: &[&'p Pattern<'tcx>],
-    constructor: &Constructor,
+    constructor: &Constructor<'tcx>,
     wild_patterns: &[&'p Pattern<'tcx>])
     -> Option<Vec<&'p Pattern<'tcx>>>
 {
@@ -1031,12 +1127,32 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
                             None
                         }
                     }
+                    ConstVal::Value(Value::ByVal(PrimVal::Ptr(ptr))) => {
+                        let is_array_ptr = value.ty
+                            .builtin_deref(true, ty::NoPreference)
+                            .and_then(|t| t.ty.builtin_index())
+                            .map_or(false, |t| t == cx.tcx.types.u8);
+                        assert!(is_array_ptr);
+                        let data_len = cx.tcx
+                            .interpret_interner
+                            .borrow()
+                            .get_alloc(ptr.alloc_id.0)
+                            .unwrap()
+                            .bytes
+                            .len();
+                        if wild_patterns.len() == data_len {
+                            Some(cx.lower_byte_str_pattern(pat))
+                        } else {
+                            None
+                        }
+                    }
                     _ => span_bug!(pat.span,
                         "unexpected const-val {:?} with ctor {:?}", value, constructor)
                 },
                 _ => {
                     match constructor_covered_by_range(
-                        cx.tcx, pat.span, constructor, &value.val, &value.val, RangeEnd::Included
+                        constructor, &value.val, &value.val, RangeEnd::Included,
+                        value.ty,
                             ) {
                         Ok(true) => Some(vec![]),
                         Ok(false) => None,
@@ -1048,7 +1164,7 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
 
         PatternKind::Range { lo, hi, ref end } => {
             match constructor_covered_by_range(
-                cx.tcx, pat.span, constructor, &lo.val, &hi.val, end.clone()
+                constructor, &lo.val, &hi.val, end.clone(), lo.ty,
             ) {
                 Ok(true) => Some(vec![]),
                 Ok(false) => None,
@@ -1092,7 +1208,7 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
             }
         }
     };
-    debug!("specialize({:?}, {:?}) = {:?}", r[0], wild_patterns, head);
+    debug!("specialize({:#?}, {:#?}) = {:#?}", r[0], wild_patterns, head);
 
     head.map(|mut head| {
         head.extend_from_slice(&r[1 ..]);
index 2a571fa82643b2d97777158abcead4396f283349..58fe40d12be849f467d10d369837f8dfd1fe9eaf 100644 (file)
@@ -26,7 +26,6 @@
 use syntax::ast;
 use syntax::attr;
 use rustc::hir::{self, Expr};
-use syntax_pos::Span;
 
 use std::cmp::Ordering;
 
@@ -104,60 +103,10 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
       hir::ExprUnary(hir::UnNeg, ref inner) => {
         // unary neg literals already got their sign during creation
         if let hir::ExprLit(ref lit) = inner.node {
-            use syntax::ast::*;
-            use syntax::ast::LitIntType::*;
-            const I8_OVERFLOW: u128 = i8::min_value() as u8 as u128;
-            const I16_OVERFLOW: u128 = i16::min_value() as u16 as u128;
-            const I32_OVERFLOW: u128 = i32::min_value() as u32 as u128;
-            const I64_OVERFLOW: u128 = i64::min_value() as u64 as u128;
-            const I128_OVERFLOW: u128 = i128::min_value() as u128;
-            let negated = match (&lit.node, &ty.sty) {
-                (&LitKind::Int(I8_OVERFLOW, _), &ty::TyInt(IntTy::I8)) |
-                (&LitKind::Int(I8_OVERFLOW, Signed(IntTy::I8)), _) => {
-                    Some(I8(i8::min_value()))
-                },
-                (&LitKind::Int(I16_OVERFLOW, _), &ty::TyInt(IntTy::I16)) |
-                (&LitKind::Int(I16_OVERFLOW, Signed(IntTy::I16)), _) => {
-                    Some(I16(i16::min_value()))
-                },
-                (&LitKind::Int(I32_OVERFLOW, _), &ty::TyInt(IntTy::I32)) |
-                (&LitKind::Int(I32_OVERFLOW, Signed(IntTy::I32)), _) => {
-                    Some(I32(i32::min_value()))
-                },
-                (&LitKind::Int(I64_OVERFLOW, _), &ty::TyInt(IntTy::I64)) |
-                (&LitKind::Int(I64_OVERFLOW, Signed(IntTy::I64)), _) => {
-                    Some(I64(i64::min_value()))
-                },
-                (&LitKind::Int(I128_OVERFLOW, _), &ty::TyInt(IntTy::I128)) |
-                (&LitKind::Int(I128_OVERFLOW, Signed(IntTy::I128)), _) => {
-                    Some(I128(i128::min_value()))
-                },
-                (&LitKind::Int(n, _), &ty::TyInt(IntTy::Isize)) |
-                (&LitKind::Int(n, Signed(IntTy::Isize)), _) => {
-                    match tcx.sess.target.isize_ty {
-                        IntTy::I16 => if n == I16_OVERFLOW {
-                            Some(Isize(Is16(i16::min_value())))
-                        } else {
-                            None
-                        },
-                        IntTy::I32 => if n == I32_OVERFLOW {
-                            Some(Isize(Is32(i32::min_value())))
-                        } else {
-                            None
-                        },
-                        IntTy::I64 => if n == I64_OVERFLOW {
-                            Some(Isize(Is64(i64::min_value())))
-                        } else {
-                            None
-                        },
-                        _ => span_bug!(e.span, "typeck error")
-                    }
-                },
-                _ => None
+            return match lit_to_const(&lit.node, tcx, ty, true) {
+                Ok(val) => Ok(mk_const(val)),
+                Err(err) => signal!(e, err),
             };
-            if let Some(i) = negated {
-                return Ok(mk_const(Integral(i)));
-            }
         }
         mk_const(match cx.eval(inner)?.val {
           Float(f) => Float(-f),
@@ -377,7 +326,7 @@ 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, ty) {
+      hir::ExprLit(ref lit) => match lit_to_const(&lit.node, tcx, ty, false) {
           Ok(val) => mk_const(val),
           Err(err) => signal!(e, err),
       },
@@ -438,7 +387,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
       }
       hir::ExprRepeat(ref elem, _) => {
           let n = match ty.sty {
-            ty::TyArray(_, n) => n.val.to_const_int().unwrap().to_u64().unwrap(),
+            ty::TyArray(_, n) => n.val.unwrap_u64(),
             _ => span_bug!(e.span, "typeck error")
           };
           mk_const(Aggregate(Repeat(cx.eval(elem)?, n)))
@@ -447,7 +396,8 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
         if let Aggregate(Tuple(fields)) = cx.eval(base)?.val {
             fields[index.node]
         } else {
-            signal!(base, ExpectedConstTuple);
+            span_bug!(base.span, "{:#?}", cx.eval(base)?.val);
+            //signal!(base, ExpectedConstTuple);
         }
       }
       hir::ExprField(ref base, field_name) => {
@@ -557,7 +507,7 @@ fn cast_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             },
             ty::TyRef(_, ty::TypeAndMut { ref ty, mutbl: hir::MutImmutable }) => match ty.sty {
                 ty::TyArray(ty, n) => {
-                    let n = n.val.to_const_int().unwrap().to_u64().unwrap();
+                    let n = n.val.unwrap_u64();
                     if ty == tcx.types.u8 && n == b.data.len() as u64 {
                         Ok(val)
                     } else {
@@ -583,13 +533,66 @@ fn cast_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 }
 
-fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind,
+pub fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind,
                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                          mut ty: Ty<'tcx>)
+                          mut ty: Ty<'tcx>,
+                          neg: bool)
                           -> Result<ConstVal<'tcx>, ErrKind<'tcx>> {
     use syntax::ast::*;
     use syntax::ast::LitIntType::*;
 
+    if tcx.sess.opts.debugging_opts.miri {
+        use rustc::mir::interpret::*;
+        let lit = match *lit {
+            LitKind::Str(ref s, _) => {
+                let s = s.as_str();
+                let id = tcx.allocate_cached(s.as_bytes());
+                let ptr = MemoryPointer::new(AllocId(id), 0);
+                Value::ByValPair(
+                    PrimVal::Ptr(ptr),
+                    PrimVal::from_u128(s.len() as u128),
+                )
+            },
+            LitKind::ByteStr(ref data) => {
+                let id = tcx.allocate_cached(data);
+                let ptr = MemoryPointer::new(AllocId(id), 0);
+                Value::ByVal(PrimVal::Ptr(ptr))
+            },
+            LitKind::Byte(n) => Value::ByVal(PrimVal::Bytes(n as u128)),
+            LitKind::Int(n, _) if neg => {
+                let n = n as i128;
+                let n = n.overflowing_neg().0;
+                Value::ByVal(PrimVal::Bytes(n as u128))
+            },
+            LitKind::Int(n, _) => Value::ByVal(PrimVal::Bytes(n as u128)),
+            LitKind::Float(n, fty) => {
+                let n = n.as_str();
+                let mut f = parse_float(&n, fty)?;
+                if neg {
+                    f = -f;
+                }
+                let bits = f.bits;
+                Value::ByVal(PrimVal::Bytes(bits))
+            }
+            LitKind::FloatUnsuffixed(n) => {
+                let fty = match ty.sty {
+                    ty::TyFloat(fty) => fty,
+                    _ => bug!()
+                };
+                let n = n.as_str();
+                let mut f = parse_float(&n, fty)?;
+                if neg {
+                    f = -f;
+                }
+                let bits = f.bits;
+                Value::ByVal(PrimVal::Bytes(bits))
+            }
+            LitKind::Bool(b) => Value::ByVal(PrimVal::Bytes(b as u128)),
+            LitKind::Char(c) => Value::ByVal(PrimVal::Bytes(c as u128)),
+        };
+        return Ok(ConstVal::Value(lit));
+    }
+
     if let ty::TyAdt(adt, _) = ty.sty {
         if adt.is_enum() {
             ty = adt.repr.discr_type().to_ty(tcx)
@@ -604,26 +607,38 @@ fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind,
             match (&ty.sty, hint) {
                 (&ty::TyInt(ity), _) |
                 (_, Signed(ity)) => {
-                    Ok(Integral(ConstInt::new_signed_truncating(n as i128,
+                    let mut n = n as i128;
+                    if neg {
+                        n = n.overflowing_neg().0;
+                    }
+                    Ok(Integral(ConstInt::new_signed_truncating(n,
                         ity, tcx.sess.target.isize_ty)))
                 }
                 (&ty::TyUint(uty), _) |
                 (_, Unsigned(uty)) => {
-                    Ok(Integral(ConstInt::new_unsigned_truncating(n as u128,
+                    Ok(Integral(ConstInt::new_unsigned_truncating(n,
                         uty, tcx.sess.target.usize_ty)))
                 }
                 _ => bug!()
             }
         }
         LitKind::Float(n, fty) => {
-            parse_float(&n.as_str(), fty).map(Float)
+            let mut f = parse_float(&n.as_str(), fty)?;
+            if neg {
+                f = -f;
+            }
+            Ok(Float(f))
         }
         LitKind::FloatUnsuffixed(n) => {
             let fty = match ty.sty {
                 ty::TyFloat(fty) => fty,
                 _ => bug!()
             };
-            parse_float(&n.as_str(), fty).map(Float)
+            let mut f = parse_float(&n.as_str(), fty)?;
+            if neg {
+                f = -f;
+            }
+            Ok(Float(f))
         }
         LitKind::Bool(b) => Ok(Bool(b)),
         LitKind::Char(c) => Ok(Char(c)),
@@ -638,36 +653,31 @@ fn parse_float<'tcx>(num: &str, fty: ast::FloatTy)
     })
 }
 
-pub fn compare_const_vals(tcx: TyCtxt, span: Span, a: &ConstVal, b: &ConstVal)
-                          -> Result<Ordering, ErrorReported>
-{
-    let result = match (a, b) {
+pub fn compare_const_vals(a: &ConstVal, b: &ConstVal, ty: Ty) -> Option<Ordering> {
+    trace!("compare_const_vals: {:?}, {:?}", a, b);
+    use rustc::mir::interpret::{Value, PrimVal};
+    match (a, b) {
         (&Integral(a), &Integral(b)) => a.try_cmp(b).ok(),
-        (&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(a), &ByteStr(b)) => Some(a.data.cmp(b.data)),
         (&Char(a), &Char(b)) => Some(a.cmp(&b)),
+        (&Value(Value::ByVal(PrimVal::Bytes(a))),
+         &Value(Value::ByVal(PrimVal::Bytes(b)))) => {
+            Some(if ty.is_signed() {
+                (a as i128).cmp(&(b as i128))
+            } else {
+                a.cmp(&b)
+            })
+        },
+        _ if a == b => Some(Ordering::Equal),
         _ => None,
-    };
-
-    match result {
-        Some(result) => Ok(result),
-        None => {
-            // FIXME: can this ever be reached?
-            tcx.sess.delay_span_bug(span,
-                &format!("type mismatch comparing {:?} and {:?}", a, b));
-            Err(ErrorReported)
-        }
     }
 }
 
 impl<'a, 'tcx> ConstContext<'a, 'tcx> {
     pub fn compare_lit_exprs(&self,
-                             span: Span,
                              a: &'tcx Expr,
-                             b: &'tcx Expr) -> Result<Ordering, ErrorReported> {
+                             b: &'tcx Expr) -> Result<Option<Ordering>, ErrorReported> {
         let tcx = self.tcx;
+        let ty = self.tables.expr_ty(a);
         let a = match self.eval(a) {
             Ok(a) => a,
             Err(e) => {
@@ -682,6 +692,6 @@ pub fn compare_lit_exprs(&self,
                 return Err(ErrorReported);
             }
         };
-        compare_const_vals(tcx, span, &a.val, &b.val)
+        Ok(compare_const_vals(&a.val, &b.val, ty))
     }
 }
index a09e2f2edd59d376027382b58d98ea4536c47bc5..a2daf22c3b45bb0ac2da13ff33dc10a84536d850 100644 (file)
@@ -10,8 +10,9 @@
 
 use eval;
 
-use rustc::middle::const_val::{ConstEvalErr, ConstVal};
+use rustc::middle::const_val::{ConstEvalErr, ConstVal, ConstAggregate};
 use rustc::mir::{Field, BorrowKind, Mutability};
+use rustc::mir::interpret::{Value, PrimVal};
 use rustc::ty::{self, TyCtxt, AdtDef, Ty, Region};
 use rustc::ty::subst::{Substs, Kind};
 use rustc::hir::{self, PatKind, RangeEnd};
@@ -110,22 +111,35 @@ pub enum PatternKind<'tcx> {
     },
 }
 
-fn print_const_val(value: &ConstVal, f: &mut fmt::Formatter) -> fmt::Result {
-    match *value {
+fn print_const_val(value: &ty::Const, f: &mut fmt::Formatter) -> fmt::Result {
+    match value.val {
         ConstVal::Float(ref x) => write!(f, "{}", x),
         ConstVal::Integral(ref i) => write!(f, "{}", i),
         ConstVal::Str(ref s) => write!(f, "{:?}", &s[..]),
         ConstVal::ByteStr(b) => write!(f, "{:?}", b.data),
         ConstVal::Bool(b) => write!(f, "{:?}", b),
         ConstVal::Char(c) => write!(f, "{:?}", c),
+        ConstVal::Value(v) => print_miri_value(v, value.ty, f),
         ConstVal::Variant(_) |
         ConstVal::Function(..) |
         ConstVal::Aggregate(_) |
-        ConstVal::Value(_) |
         ConstVal::Unevaluated(..) => bug!("{:?} not printable in a pattern", value)
     }
 }
 
+fn print_miri_value(value: Value, ty: Ty, f: &mut fmt::Formatter) -> fmt::Result {
+    use rustc::ty::TypeVariants::*;
+    match (value, &ty.sty) {
+        (Value::ByVal(PrimVal::Bytes(0)), &TyBool) => write!(f, "false"),
+        (Value::ByVal(PrimVal::Bytes(1)), &TyBool) => write!(f, "true"),
+        (Value::ByVal(PrimVal::Bytes(n)), &TyUint(..)) => write!(f, "{:?}", n),
+        (Value::ByVal(PrimVal::Bytes(n)), &TyInt(..)) => write!(f, "{:?}", n as i128),
+        (Value::ByVal(PrimVal::Bytes(n)), &TyChar) =>
+            write!(f, "{:?}", ::std::char::from_u32(n as u32).unwrap()),
+        _ => bug!("{:?}: {} not printable in a pattern", value, ty),
+    }
+}
+
 impl<'tcx> fmt::Display for Pattern<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self.kind {
@@ -233,15 +247,15 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                 write!(f, "{}", subpattern)
             }
             PatternKind::Constant { value } => {
-                print_const_val(&value.val, f)
+                print_const_val(value, f)
             }
             PatternKind::Range { lo, hi, end } => {
-                print_const_val(&lo.val, f)?;
+                print_const_val(lo, f)?;
                 match end {
                     RangeEnd::Included => write!(f, "...")?,
                     RangeEnd::Excluded => write!(f, "..")?,
                 }
-                print_const_val(&hi.val, f)
+                print_const_val(hi, f)
             }
             PatternKind::Slice { ref prefix, ref slice, ref suffix } |
             PatternKind::Array { ref prefix, ref slice, ref suffix } => {
@@ -362,7 +376,7 @@ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat) -> Pattern<'tcx> {
             }
 
             PatKind::Path(ref qpath) => {
-                return self.lower_path(qpath, pat.hir_id, pat.id, pat.span);
+                return self.lower_path(qpath, pat.hir_id, pat.span);
             }
 
             PatKind::Ref(ref subpattern, _) |
@@ -581,7 +595,7 @@ fn slice_or_array_pattern(
 
             ty::TyArray(_, len) => {
                 // fixed-length array
-                let len = len.val.to_const_int().unwrap().to_u64().unwrap();
+                let len = len.val.unwrap_u64();
                 assert!(len >= prefix.len() as u64 + suffix.len() as u64);
                 PatternKind::Array { prefix: prefix, slice: slice, suffix: suffix }
             }
@@ -632,7 +646,6 @@ fn lower_variant_or_leaf(
     fn lower_path(&mut self,
                   qpath: &hir::QPath,
                   id: hir::HirId,
-                  pat_id: ast::NodeId,
                   span: Span)
                   -> Pattern<'tcx> {
         let ty = self.tables.node_id_to_type(id);
@@ -644,29 +657,23 @@ fn lower_path(&mut self,
         let kind = match def {
             Def::Const(def_id) | Def::AssociatedConst(def_id) => {
                 let substs = self.tables.node_substs(id);
-                match eval::lookup_const_by_id(self.tcx, self.param_env.and((def_id, substs))) {
-                    Some((def_id, substs)) => {
-                        // Enter the inlined constant's tables&substs temporarily.
-                        let old_tables = self.tables;
-                        let old_substs = self.substs;
-                        self.tables = self.tcx.typeck_tables_of(def_id);
-                        self.substs = substs;
-                        let body = if let Some(id) = self.tcx.hir.as_local_node_id(def_id) {
-                            self.tcx.hir.body(self.tcx.hir.body_owned_by(id))
-                        } else {
-                            self.tcx.extern_const_body(def_id).body
-                        };
-                        let pat = self.lower_const_expr(&body.value, pat_id, span);
-                        self.tables = old_tables;
-                        self.substs = old_substs;
-                        return pat;
-                    }
-                    None => {
-                        self.errors.push(if is_associated_const {
-                            PatternError::AssociatedConstInPattern(span)
-                        } else {
-                            PatternError::StaticInPattern(span)
-                        });
+                match self.tcx.at(span).const_eval(self.param_env.and((def_id, substs))) {
+                    Ok(value) => {
+                        if self.tcx.sess.opts.debugging_opts.miri {
+                            if let ConstVal::Value(_) = value.val {} else {
+                                panic!("const eval produced non-miri value: {:#?}", value);
+                            }
+                        }
+                        let instance = ty::Instance::resolve(
+                            self.tcx,
+                            self.param_env,
+                            def_id,
+                            substs,
+                        ).unwrap();
+                        return self.const_to_pat(instance, value, span)
+                    },
+                    Err(e) => {
+                        self.errors.push(PatternError::ConstEval(e));
                         PatternKind::Wild
                     }
                 }
@@ -682,6 +689,52 @@ fn lower_path(&mut self,
     }
 
     fn lower_lit(&mut self, expr: &'tcx hir::Expr) -> PatternKind<'tcx> {
+        if self.tcx.sess.opts.debugging_opts.miri {
+            return match expr.node {
+                hir::ExprLit(ref lit) => {
+                    let ty = self.tables.expr_ty(expr);
+                    match ::eval::lit_to_const(&lit.node, self.tcx, ty, false) {
+                        Ok(value) => PatternKind::Constant {
+                            value: self.tcx.mk_const(ty::Const {
+                                ty,
+                                val: value,
+                            }),
+                        },
+                        Err(e) => {
+                            self.errors.push(PatternError::ConstEval(ConstEvalErr {
+                                span: lit.span,
+                                kind: e,
+                            }));
+                            PatternKind::Wild
+                        },
+                    }
+                },
+                hir::ExprPath(ref qpath) => *self.lower_path(qpath, expr.hir_id, expr.span).kind,
+                hir::ExprUnary(hir::UnNeg, ref expr) => {
+                    let ty = self.tables.expr_ty(expr);
+                    let lit = match expr.node {
+                        hir::ExprLit(ref lit) => lit,
+                        _ => span_bug!(expr.span, "not a literal: {:?}", expr),
+                    };
+                    match ::eval::lit_to_const(&lit.node, self.tcx, ty, true) {
+                        Ok(value) => PatternKind::Constant {
+                            value: self.tcx.mk_const(ty::Const {
+                                ty,
+                                val: value,
+                            }),
+                        },
+                        Err(e) => {
+                            self.errors.push(PatternError::ConstEval(ConstEvalErr {
+                                span: lit.span,
+                                kind: e,
+                            }));
+                            PatternKind::Wild
+                        },
+                    }
+                }
+                _ => span_bug!(expr.span, "not a literal: {:?}", expr),
+            }
+        }
         let const_cx = eval::ConstContext::new(self.tcx,
                                                self.param_env.and(self.substs),
                                                self.tables);
@@ -701,118 +754,156 @@ fn lower_lit(&mut self, expr: &'tcx hir::Expr) -> PatternKind<'tcx> {
         }
     }
 
-    fn lower_const_expr(&mut self,
-                        expr: &'tcx hir::Expr,
-                        pat_id: ast::NodeId,
-                        span: Span)
-                        -> Pattern<'tcx> {
-        let pat_ty = self.tables.expr_ty(expr);
-        debug!("expr={:?} pat_ty={:?} pat_id={}", expr, pat_ty, pat_id);
-        match pat_ty.sty {
+    fn const_to_pat(
+        &self,
+        instance: ty::Instance<'tcx>,
+        cv: &'tcx ty::Const<'tcx>,
+        span: Span,
+    ) -> Pattern<'tcx> {
+        debug!("const_to_pat: cv={:#?}", cv);
+        let kind = match cv.ty.sty {
             ty::TyFloat(_) => {
                 self.tcx.sess.span_err(span, "floating point constants cannot be used in patterns");
+                PatternKind::Wild
             }
             ty::TyAdt(adt_def, _) if adt_def.is_union() => {
                 // Matching on union fields is unsafe, we can't hide it in constants
                 self.tcx.sess.span_err(span, "cannot use unions in constant patterns");
+                PatternKind::Wild
             }
+            ty::TyAdt(adt_def, _) if !self.tcx.has_attr(adt_def.did, "structural_match") => {
+                let msg = format!("to use a constant of type `{}` in a pattern, \
+                                    `{}` must be annotated with `#[derive(PartialEq, Eq)]`",
+                                    self.tcx.item_path_str(adt_def.did),
+                                    self.tcx.item_path_str(adt_def.did));
+                self.tcx.sess.span_err(span, &msg);
+                PatternKind::Wild
+            },
+            ty::TyAdt(adt_def, substs) if adt_def.is_enum() => {
+                match cv.val {
+                    ConstVal::Value(val) => {
+                        let discr = self.tcx.const_discr(self.param_env.and((
+                            instance, val, cv.ty
+                        ))).unwrap();
+                        let variant_index = adt_def
+                            .discriminants(self.tcx)
+                            .position(|var| var.to_u128_unchecked() == discr)
+                            .unwrap();
+                        PatternKind::Variant {
+                            adt_def,
+                            substs,
+                            variant_index,
+                            subpatterns: adt_def
+                                .variants[variant_index]
+                                .fields
+                                .iter()
+                                .enumerate()
+                                .map(|(i, _)| {
+                                let field = Field::new(i);
+                                let val = match cv.val {
+                                    ConstVal::Value(miri) => self.tcx.const_val_field(
+                                        self.param_env.and((instance, field, miri, cv.ty)),
+                                    ).unwrap(),
+                                    _ => bug!("{:#?} is not a valid tuple", cv),
+                                };
+                                FieldPattern {
+                                    field,
+                                    pattern: self.const_to_pat(instance, val, span),
+                                }
+                            }).collect(),
+                        }
+                    },
+                    ConstVal::Variant(var_did) => {
+                        let variant_index = adt_def
+                            .variants
+                            .iter()
+                            .position(|var| var.did == var_did)
+                            .unwrap();
+                        PatternKind::Variant {
+                            adt_def,
+                            substs,
+                            variant_index,
+                            subpatterns: Vec::new(),
+                        }
+                    }
+                    _ => return Pattern {
+                        span,
+                        ty: cv.ty,
+                        kind: Box::new(PatternKind::Constant {
+                            value: cv,
+                        }),
+                    }
+                }
+            },
             ty::TyAdt(adt_def, _) => {
-                if !self.tcx.has_attr(adt_def.did, "structural_match") {
-                    let msg = format!("to use a constant of type `{}` in a pattern, \
-                                       `{}` must be annotated with `#[derive(PartialEq, Eq)]`",
-                                      self.tcx.item_path_str(adt_def.did),
-                                      self.tcx.item_path_str(adt_def.did));
-                    self.tcx.sess.span_err(span, &msg);
+                let struct_var = adt_def.struct_variant();
+                PatternKind::Leaf {
+                    subpatterns: struct_var.fields.iter().enumerate().map(|(i, f)| {
+                        let field = Field::new(i);
+                        let val = match cv.val {
+                            ConstVal::Aggregate(ConstAggregate::Struct(consts)) => {
+                                consts.iter().find(|&&(name, _)| name == f.name).unwrap().1
+                            },
+                            ConstVal::Value(miri) => self.tcx.const_val_field(
+                                self.param_env.and((instance, field, miri, cv.ty)),
+                            ).unwrap(),
+                            _ => bug!("{:#?} is not a valid tuple", cv),
+                        };
+                        FieldPattern {
+                            field,
+                            pattern: self.const_to_pat(instance, val, span),
+                        }
+                    }).collect()
                 }
             }
-            _ => { }
-        }
-        let kind = match expr.node {
-            hir::ExprTup(ref exprs) => {
+            ty::TyTuple(fields, _) => {
                 PatternKind::Leaf {
-                    subpatterns: exprs.iter().enumerate().map(|(i, expr)| {
+                    subpatterns: (0..fields.len()).map(|i| {
+                        let field = Field::new(i);
+                        let val = match cv.val {
+                            ConstVal::Aggregate(ConstAggregate::Tuple(consts)) => consts[i],
+                            ConstVal::Value(miri) => self.tcx.const_val_field(
+                                self.param_env.and((instance, field, miri, cv.ty)),
+                            ).unwrap(),
+                            _ => bug!("{:#?} is not a valid tuple", cv),
+                        };
                         FieldPattern {
-                            field: Field::new(i),
-                            pattern: self.lower_const_expr(expr, pat_id, span)
+                            field,
+                            pattern: self.const_to_pat(instance, val, span),
                         }
                     }).collect()
                 }
             }
-
-            hir::ExprCall(ref callee, ref args) => {
-                let qpath = match callee.node {
-                    hir::ExprPath(ref qpath) => qpath,
-                    _ => bug!()
-                };
-                let ty = self.tables.node_id_to_type(callee.hir_id);
-                let def = self.tables.qpath_def(qpath, callee.hir_id);
-                match def {
-                    Def::Fn(..) | Def::Method(..) => self.lower_lit(expr),
-                    _ => {
-                        let subpatterns = args.iter().enumerate().map(|(i, expr)| {
-                            FieldPattern {
-                                field: Field::new(i),
-                                pattern: self.lower_const_expr(expr, pat_id, span)
-                            }
-                        }).collect();
-                        self.lower_variant_or_leaf(def, ty, subpatterns)
-                    }
+            ty::TyArray(_, n) => {
+                PatternKind::Leaf {
+                    subpatterns: (0..n.val.unwrap_u64()).map(|i| {
+                        let i = i as usize;
+                        let field = Field::new(i);
+                        let val = match cv.val {
+                            ConstVal::Aggregate(ConstAggregate::Array(consts)) => consts[i],
+                            ConstVal::Aggregate(ConstAggregate::Repeat(cv, _)) => cv,
+                            ConstVal::Value(miri) => self.tcx.const_val_field(
+                                self.param_env.and((instance, field, miri, cv.ty)),
+                            ).unwrap(),
+                            _ => bug!("{:#?} is not a valid tuple", cv),
+                        };
+                        FieldPattern {
+                            field,
+                            pattern: self.const_to_pat(instance, val, span),
+                        }
+                    }).collect()
                 }
             }
-
-            hir::ExprStruct(ref qpath, ref fields, None) => {
-                let def = self.tables.qpath_def(qpath, expr.hir_id);
-                let adt_def = match pat_ty.sty {
-                    ty::TyAdt(adt_def, _) => adt_def,
-                    _ => {
-                        span_bug!(
-                            expr.span,
-                            "struct expr without ADT type");
-                    }
-                };
-                let variant_def = adt_def.variant_of_def(def);
-
-                let subpatterns =
-                    fields.iter()
-                          .map(|field| {
-                              let index = variant_def.index_of_field_named(field.name.node);
-                              let index = index.unwrap_or_else(|| {
-                                  span_bug!(
-                                      expr.span,
-                                      "no field with name {:?}",
-                                      field.name);
-                              });
-                              FieldPattern {
-                                  field: Field::new(index),
-                                  pattern: self.lower_const_expr(&field.expr, pat_id, span),
-                              }
-                          })
-                          .collect();
-
-                self.lower_variant_or_leaf(def, pat_ty, subpatterns)
-            }
-
-            hir::ExprArray(ref exprs) => {
-                let pats = exprs.iter()
-                                .map(|expr| self.lower_const_expr(expr, pat_id, span))
-                                .collect();
-                PatternKind::Array {
-                    prefix: pats,
-                    slice: None,
-                    suffix: vec![]
+            _ => {
+                PatternKind::Constant {
+                    value: cv,
                 }
-            }
-
-            hir::ExprPath(ref qpath) => {
-                return self.lower_path(qpath, expr.hir_id, pat_id, span);
-            }
-
-            _ => self.lower_lit(expr)
+            },
         };
 
         Pattern {
             span,
-            ty: pat_ty,
+            ty: cv.ty,
             kind: Box::new(kind),
         }
     }
index d82b712b5b14b983403e49413a4f80f613073cc0..70733bc6aeda042e826b95787e9ea26047baee37 100644 (file)
@@ -259,6 +259,14 @@ fn hash_stable<W: StableHasherResult>(&self,
     }
 }
 
+impl<CTX> HashStable<CTX> for ::std::cmp::Ordering {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          ctx: &mut CTX,
+                                          hasher: &mut StableHasher<W>) {
+        (*self as i8).hash_stable(ctx, hasher);
+    }
+}
+
 impl<T1: HashStable<CTX>, CTX> HashStable<CTX> for (T1,) {
     fn hash_stable<W: StableHasherResult>(&self,
                                           ctx: &mut CTX,
index 1c4bd0ff4c2ec1335ab7429dee64d7b96f00d42a..f400ce42a90469d6eec27a65fd555e4c06bf7b41 100644 (file)
@@ -16,6 +16,7 @@
 use rustc::ty::layout::{self, LayoutOf};
 use middle::const_val::ConstVal;
 use rustc_const_eval::ConstContext;
+use rustc::mir::interpret::{Value, PrimVal};
 use util::nodemap::FxHashSet;
 use lint::{LateContext, LintContext, LintArray};
 use lint::{LintPass, LateLintPass};
@@ -122,6 +123,16 @@ fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx hir::Expr) {
                                         .map(|i| i >= bits)
                                         .unwrap_or(true)
                                 }
+                                Ok(&ty::Const {
+                                    val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(b))),
+                                    ty,
+                                }) => {
+                                    if ty.is_signed() {
+                                        (b as i128) < 0
+                                    } else {
+                                        b >= bits as u128
+                                    }
+                                }
                                 _ => false,
                             }
                         };
index 3c3c489d0ff783b1a4ac3876e80ab70d0259db6b..1663cab0a592e5f473400f4597d2f384b90fa7f8 100644 (file)
@@ -276,38 +276,54 @@ fn specialized_decode(&mut self) -> Result<DefIndex, Self::Error> {
 impl<'a, 'tcx> SpecializedDecoder<interpret::AllocId> for DecodeContext<'a, 'tcx> {
     fn specialized_decode(&mut self) -> Result<interpret::AllocId, Self::Error> {
         const MAX1: usize = usize::max_value() - 1;
-        let mut interpret_interner = self.tcx.unwrap().interpret_interner.borrow_mut();
+        let tcx = self.tcx;
+        let interpret_interner = || tcx.unwrap().interpret_interner.borrow_mut();
         let pos = self.position();
-        match self.read_usize()? {
+        match usize::decode(self)? {
             ::std::usize::MAX => {
+                let id = interpret_interner().reserve();
+                let alloc_id = interpret::AllocId(id);
+                trace!("creating alloc id {:?} at {}", alloc_id, pos);
+                // insert early to allow recursive allocs
+                self.interpret_alloc_cache.insert(pos, alloc_id);
+
                 let allocation = interpret::Allocation::decode(self)?;
-                let id = interpret_interner.reserve();
+                trace!("decoded alloc {:?} {:#?}", alloc_id, allocation);
                 let allocation = self.tcx.unwrap().intern_const_alloc(allocation);
-                interpret_interner.intern_at_reserved(id, allocation);
-                let id = interpret::AllocId(id);
-                self.interpret_alloc_cache.insert(pos, id);
+                interpret_interner().intern_at_reserved(id, allocation);
 
                 let num = usize::decode(self)?;
                 let ptr = interpret::Pointer {
                     primval: interpret::PrimVal::Ptr(interpret::MemoryPointer {
-                        alloc_id: id,
+                        alloc_id,
                         offset: 0,
                     }),
                 };
                 for _ in 0..num {
                     let glob = interpret::GlobalId::decode(self)?;
-                    interpret_interner.cache(glob, ptr);
+                    interpret_interner().cache(glob, ptr);
                 }
 
-                Ok(id)
+                Ok(alloc_id)
             },
             MAX1 => {
+                trace!("creating fn alloc id at {}", pos);
                 let instance = ty::Instance::decode(self)?;
-                let id = interpret::AllocId(interpret_interner.create_fn_alloc(instance));
+                trace!("decoded fn alloc instance: {:?}", instance);
+                let id = interpret::AllocId(interpret_interner().create_fn_alloc(instance));
+                trace!("created fn alloc id: {:?}", id);
                 self.interpret_alloc_cache.insert(pos, id);
                 Ok(id)
             },
-            shorthand => Ok(self.interpret_alloc_cache[&shorthand]),
+            shorthand => {
+                trace!("loading shorthand {}", shorthand);
+                if let Some(&alloc_id) = self.interpret_alloc_cache.get(&shorthand) {
+                    return Ok(alloc_id);
+                }
+                trace!("shorthand {} not cached, loading entire allocation", shorthand);
+                // need to load allocation
+                self.with_position(shorthand, |this| interpret::AllocId::decode(this))
+            },
         }
     }
 }
index 928bf0a56ae51398db0658bb845cf262ef932ec2..1e1baba2bac5e708175aa69c66501bcf3883bab6 100644 (file)
@@ -189,12 +189,18 @@ fn specialized_encode(&mut self, ty: &Ty<'tcx>) -> Result<(), Self::Error> {
 
 impl<'a, 'tcx> SpecializedEncoder<interpret::AllocId> for EncodeContext<'a, 'tcx> {
     fn specialized_encode(&mut self, alloc_id: &interpret::AllocId) -> Result<(), Self::Error> {
+        trace!("encoding {:?} at {}", alloc_id, self.position());
         if let Some(shorthand) = self.interpret_alloc_shorthands.get(alloc_id).cloned() {
-            return self.emit_usize(shorthand);
+            trace!("encoding {:?} as shorthand to {}", alloc_id, shorthand);
+            return shorthand.encode(self);
         }
         let start = self.position();
+        // cache the allocation shorthand now, because the allocation itself might recursively
+        // point to itself.
+        self.interpret_alloc_shorthands.insert(*alloc_id, start);
         let interpret_interner = self.tcx.interpret_interner.borrow();
         if let Some(alloc) = interpret_interner.get_alloc(alloc_id.0) {
+            trace!("encoding {:?} with {:#?}", alloc_id, alloc);
             usize::max_value().encode(self)?;
             alloc.encode(self)?;
             let globals = interpret_interner.get_globals(interpret::Pointer {
@@ -208,16 +214,12 @@ fn specialized_encode(&mut self, alloc_id: &interpret::AllocId) -> Result<(), Se
                 glob.encode(self)?;
             }
         } else if let Some(fn_instance) = interpret_interner.get_fn(alloc_id.0) {
+            trace!("encoding {:?} with {:#?}", alloc_id, fn_instance);
             (usize::max_value() - 1).encode(self)?;
             fn_instance.encode(self)?;
         } else {
             bug!("alloc id without corresponding allocation: {}", alloc_id.0);
         }
-        let len = self.position() - start * 7;
-        // Check that the shorthand is a not longer than the
-        // full encoding itself, i.e. it's an obvious win.
-        assert!(len >= 64 || (start as u64) < (1 << len));
-        self.interpret_alloc_shorthands.insert(*alloc_id, start);
         Ok(())
     }
 }
index bbf4357e5b0f91edf5b2c07d2aa93b8cfa4f9154..5955d0ca59adfe77f4f6b62bae8b4e66fee37473 100644 (file)
@@ -26,6 +26,7 @@
 use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeVariants};
 use rustc::middle::const_val::ConstVal;
 use rustc::mir::*;
+use rustc::mir::interpret::{Value, PrimVal};
 use rustc::mir::tcx::PlaceTy;
 use rustc::mir::visit::{PlaceContext, Visitor};
 use std::fmt;
@@ -258,7 +259,24 @@ fn sanitize_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
                 // constraints on `'a` and `'b`. These constraints
                 // would be lost if we just look at the normalized
                 // value.
-                if let ConstVal::Function(def_id, ..) = value.val {
+                let did = match value.val {
+                    ConstVal::Function(def_id, ..) => Some(def_id),
+                    ConstVal::Value(Value::ByVal(PrimVal::Ptr(p))) => {
+                        self.tcx()
+                            .interpret_interner
+                            .borrow()
+                            .get_fn(p.alloc_id.0)
+                            .map(|instance| instance.def_id())
+                    },
+                    ConstVal::Value(Value::ByVal(PrimVal::Undef)) => {
+                        match value.ty.sty {
+                            ty::TyFnDef(ty_def_id, _) => Some(ty_def_id),
+                            _ => None,
+                        }
+                    },
+                    _ => None,
+                };
+                if let Some(def_id) = did {
                     let tcx = self.tcx();
                     let type_checker = &mut self.cx;
 
@@ -436,7 +454,7 @@ fn sanitize_projection(
             ProjectionElem::Subslice { from, to } => PlaceTy::Ty {
                 ty: match base_ty.sty {
                     ty::TyArray(inner, size) => {
-                        let size = size.val.to_const_int().unwrap().to_u64().unwrap();
+                        let size = size.val.unwrap_u64();
                         let min_size = (from as u64) + (to as u64);
                         if let Some(rest_size) = size.checked_sub(min_size) {
                             tcx.mk_array(inner, rest_size)
@@ -1019,13 +1037,32 @@ fn is_box_free(&self, operand: &Operand<'tcx>) -> bool {
                     Literal::Value {
                         value:
                             &ty::Const {
-                                val: ConstVal::Function(def_id, _),
-                                ..
+                                val,
+                                ty,
                             },
                         ..
                     },
                 ..
-            }) => Some(def_id) == self.tcx().lang_items().box_free_fn(),
+            }) => match val {
+                ConstVal::Function(def_id, _) => {
+                    Some(def_id) == self.tcx().lang_items().box_free_fn()
+                },
+                ConstVal::Value(Value::ByVal(PrimVal::Ptr(p))) => {
+                    let inst = self.tcx().interpret_interner.borrow().get_fn(p.alloc_id.0);
+                    inst.map_or(false, |inst| {
+                        Some(inst.def_id()) == self.tcx().lang_items().box_free_fn()
+                    })
+                },
+                ConstVal::Value(Value::ByVal(PrimVal::Undef)) => {
+                    match ty.sty {
+                        ty::TyFnDef(ty_def_id, _) => {
+                            Some(ty_def_id) == self.tcx().lang_items().box_free_fn()
+                        }
+                        _ => false,
+                    }
+                }
+                _ => false,
+            }
             _ => false,
         }
     }
index d3cc952759058981826a5f504714aac17437967f..b5b8f8d7e78b0a553d7ff105eec4e7a5d1d570a2 100644 (file)
@@ -24,6 +24,7 @@
 use rustc::middle::region;
 use rustc::ty::{self, Ty};
 use rustc::mir::*;
+use rustc::mir::interpret::{Value, PrimVal};
 use syntax::ast;
 use syntax_pos::Span;
 
@@ -203,7 +204,11 @@ fn expr_as_rvalue(&mut self,
                         ty: this.hir.tcx().types.u32,
                         literal: Literal::Value {
                             value: this.hir.tcx().mk_const(ty::Const {
-                                val: ConstVal::Integral(ConstInt::U32(0)),
+                                val: if this.hir.tcx().sess.opts.debugging_opts.miri {
+                                    ConstVal::Value(Value::ByVal(PrimVal::Bytes(0)))
+                                } else {
+                                    ConstVal::Integral(ConstInt::U32(0))
+                                },
                                 ty: this.hir.tcx().types.u32
                             }),
                         },
@@ -401,7 +406,11 @@ fn neg_1_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
 
                 Literal::Value {
                     value: self.hir.tcx().mk_const(ty::Const {
-                        val: ConstVal::Integral(val),
+                        val: if self.hir.tcx().sess.opts.debugging_opts.miri {
+                            ConstVal::Value(Value::ByVal(PrimVal::Bytes(val.to_u128_unchecked())))
+                        } else {
+                            ConstVal::Integral(val)
+                        },
                         ty
                     })
                 }
@@ -439,7 +448,13 @@ fn minval_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
 
                 Literal::Value {
                     value: self.hir.tcx().mk_const(ty::Const {
-                        val: ConstVal::Integral(val),
+                        val: if self.hir.tcx().sess.opts.debugging_opts.miri {
+                            ConstVal::Value(Value::ByVal(PrimVal::Bytes(
+                                val.to_u128_unchecked()
+                            )))
+                        } else {
+                            ConstVal::Integral(val)
+                        },
                         ty
                     })
                 }
index 58ce572ae8d88abd79e7936d6f871fbc4b72cf92..229e33dcd786209fc49b67322248a6b3fb6cc696 100644 (file)
@@ -354,7 +354,7 @@ enum TestKind<'tcx> {
     // test the branches of enum
     SwitchInt {
         switch_ty: Ty<'tcx>,
-        options: Vec<&'tcx ty::Const<'tcx>>,
+        options: Vec<u128>,
         indices: FxHashMap<&'tcx ty::Const<'tcx>, usize>,
     },
 
index bdcbfc0bdd85e9f6506216ac340d219cfcdb67a3..fafdee5b1e1b9cde3273725a92749c507a1d4e13 100644 (file)
@@ -24,6 +24,7 @@
 use rustc::ty::{self, Ty};
 use rustc::ty::util::IntTypeExt;
 use rustc::mir::*;
+use rustc::mir::interpret::{Value, PrimVal};
 use rustc::hir::RangeEnd;
 use syntax_pos::Span;
 use std::cmp::Ordering;
@@ -112,7 +113,7 @@ pub fn add_cases_to_switch<'pat>(&mut self,
                                      test_place: &Place<'tcx>,
                                      candidate: &Candidate<'pat, 'tcx>,
                                      switch_ty: Ty<'tcx>,
-                                     options: &mut Vec<&'tcx ty::Const<'tcx>>,
+                                     options: &mut Vec<u128>,
                                      indices: &mut FxHashMap<&'tcx ty::Const<'tcx>, usize>)
                                      -> bool
     {
@@ -128,7 +129,7 @@ pub fn add_cases_to_switch<'pat>(&mut self,
 
                 indices.entry(value)
                        .or_insert_with(|| {
-                           options.push(value);
+                           options.push(value.val.to_u128().expect("switching on int"));
                            options.len() - 1
                        });
                 true
@@ -231,7 +232,7 @@ pub fn perform_test(&mut self,
                 let tcx = self.hir.tcx();
                 for (idx, discr) in adt_def.discriminants(tcx).enumerate() {
                     target_blocks.place_back() <- if variants.contains(idx) {
-                        values.push(discr);
+                        values.push(discr.to_u128_unchecked());
                         *(targets.place_back() <- self.cfg.start_new_block())
                     } else {
                         if otherwise_block.is_none() {
@@ -266,9 +267,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].val {
-                        ConstVal::Bool(true) => vec![true_bb, false_bb],
-                        ConstVal::Bool(false) => vec![false_bb, true_bb],
+                    let ret = match options[0] {
+                        1 => vec![true_bb, false_bb],
+                        0 => vec![false_bb, true_bb],
                         v => span_bug!(test.span, "expected boolean value but got {:?}", v)
                     };
                     (ret, TerminatorKind::if_(self.hir.tcx(), Operand::Copy(place.clone()),
@@ -282,13 +283,10 @@ pub fn perform_test(&mut self,
                                .map(|_| self.cfg.start_new_block())
                                .chain(Some(otherwise))
                                .collect();
-                    let values: Vec<_> = options.iter().map(|v|
-                        v.val.to_const_int().expect("switching on integral")
-                    ).collect();
                     (targets.clone(), TerminatorKind::SwitchInt {
                         discr: Operand::Copy(place.clone()),
                         switch_ty,
-                        values: From::from(values),
+                        values: options.clone().into(),
                         targets,
                     })
                 };
@@ -300,14 +298,49 @@ pub fn perform_test(&mut self,
                 let tcx = self.hir.tcx();
                 let mut val = Operand::Copy(place.clone());
 
+                let bytes = match value.val {
+                    ConstVal::ByteStr(bytes) => Some(bytes.data),
+                    ConstVal::Value(Value::ByVal(PrimVal::Ptr(p))) => {
+                        let is_array_ptr = ty
+                            .builtin_deref(true, ty::NoPreference)
+                            .and_then(|t| t.ty.builtin_index())
+                            .map_or(false, |t| t == self.hir.tcx().types.u8);
+                        if is_array_ptr {
+                            self.hir
+                                .tcx()
+                                .interpret_interner
+                                .borrow()
+                                .get_alloc(p.alloc_id.0)
+                                .map(|alloc| &alloc.bytes[..])
+                        } else {
+                            None
+                        }
+                    },
+                    _ => None,
+                };
                 // If we're using b"..." as a pattern, we need to insert an
                 // unsizing coercion, as the byte string has the type &[u8; N].
                 //
                 // We want to do this even when the scrutinee is a reference to an
                 // array, so we can call `<[u8]>::eq` rather than having to find an
                 // `<[u8; N]>::eq`.
-                let (expect, val) = if let ConstVal::ByteStr(bytes) = value.val {
-                    let array_ty = tcx.mk_array(tcx.types.u8, bytes.data.len() as u64);
+                let expect = if let Some(bytes) = bytes {
+                    let tcx = self.hir.tcx();
+
+                    // Unsize the place to &[u8], too, if necessary.
+                    if let ty::TyRef(region, mt) = ty.sty {
+                        if let ty::TyArray(_, _) = mt.ty.sty {
+                            ty = tcx.mk_imm_ref(region, tcx.mk_slice(tcx.types.u8));
+                            let val_slice = self.temp(ty, test.span);
+                            self.cfg.push_assign(block, source_info, &val_slice,
+                                                 Rvalue::Cast(CastKind::Unsize, val, ty));
+                            val = Operand::Move(val_slice);
+                        }
+                    }
+
+                    assert!(ty.is_slice());
+
+                    let array_ty = tcx.mk_array(tcx.types.u8, bytes.len() as u64);
                     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
@@ -324,11 +357,15 @@ pub fn perform_test(&mut self,
 
                 // Use PartialEq::eq for &str and &[u8] slices, instead of BinOp::Eq.
                 let fail = self.cfg.start_new_block();
-                let ty = expect.ty(&self.local_decls, tcx);
-                if let ty::TyRef(_, mt) = ty.sty {
-                    assert!(ty.is_slice());
+                let str_or_bytestr = ty
+                    .builtin_deref(true, ty::NoPreference)
+                    .and_then(|tam| match tam.ty.sty {
+                        ty::TyStr => Some(tam.ty),
+                        ty::TySlice(inner) if inner == self.hir.tcx().types.u8 => Some(tam.ty),
+                        _ => None,
+                    });
+                if let Some(ty) = str_or_bytestr {
                     let eq_def_id = self.hir.tcx().lang_items().eq_trait().unwrap();
-                    let ty = mt.ty;
                     let (mty, method) = self.hir.trait_method(eq_def_id, "eq", ty, &[ty]);
 
                     let bool_ty = self.hir.bool_ty();
index a3350cb1671d26e94a41cb97670d8ac3a8d6e41f..efb367201189bd36d59c60f1119d8641aba4f6b3 100644 (file)
@@ -16,6 +16,7 @@
 use rustc_const_math::{ConstInt, ConstUsize, ConstIsize};
 use rustc::middle::const_val::ConstVal;
 use rustc::ty::{self, Ty};
+use rustc::mir::interpret::{Value, PrimVal};
 
 use rustc::mir::*;
 use syntax::ast;
@@ -62,7 +63,11 @@ pub fn zero_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
             ty::TyChar => {
                 Literal::Value {
                     value: self.hir.tcx().mk_const(ty::Const {
-                        val: ConstVal::Char('\0'),
+                        val: if self.hir.tcx().sess.opts.debugging_opts.miri {
+                            ConstVal::Value(Value::ByVal(PrimVal::Bytes(0)))
+                        } else {
+                            ConstVal::Char('\0')
+                        },
                         ty
                     })
                 }
@@ -83,7 +88,11 @@ pub fn zero_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
 
                 Literal::Value {
                     value: self.hir.tcx().mk_const(ty::Const {
-                        val: ConstVal::Integral(val),
+                        val: if self.hir.tcx().sess.opts.debugging_opts.miri {
+                            ConstVal::Value(Value::ByVal(PrimVal::Bytes(0)))
+                        } else {
+                            ConstVal::Integral(val)
+                        },
                         ty
                     })
                 }
@@ -104,7 +113,11 @@ pub fn zero_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
 
                 Literal::Value {
                     value: self.hir.tcx().mk_const(ty::Const {
-                        val: ConstVal::Integral(val),
+                        val: if self.hir.tcx().sess.opts.debugging_opts.miri {
+                            ConstVal::Value(Value::ByVal(PrimVal::Bytes(0)))
+                        } else {
+                            ConstVal::Integral(val)
+                        },
                         ty
                     })
                 }
index 00ab2e4599528f3de48828ff454a454f83b75042..198e55358e7ee5f01fe61d2015ce3ae570b1fd15 100644 (file)
@@ -10,7 +10,6 @@
 
 use hair::*;
 use rustc_data_structures::indexed_vec::Idx;
-use rustc_const_math::ConstInt;
 use hair::cx::Cx;
 use hair::cx::block;
 use hair::cx::to_ref::ToRef;
@@ -18,6 +17,7 @@
 use rustc::middle::const_val::ConstVal;
 use rustc::ty::{self, AdtKind, VariantDef, Ty};
 use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability};
+use rustc::mir::interpret::{Value, PrimVal};
 use rustc::ty::cast::CastKind as TyCastKind;
 use rustc::hir;
 use rustc::hir::def_id::LocalDefId;
@@ -100,7 +100,7 @@ fn apply_adjustment<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
             ExprKind::Deref { arg: expr.to_ref() }
         }
         Adjust::Deref(Some(deref)) => {
-            let call = deref.method_call(cx.tcx, expr.ty);
+            let call = deref.method_call(cx.tcx(), expr.ty);
 
             expr = Expr {
                 temp_lifetime,
@@ -314,7 +314,9 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
             }
         }
 
-        hir::ExprLit(..) => ExprKind::Literal { literal: cx.const_eval_literal(expr) },
+        hir::ExprLit(ref lit) => ExprKind::Literal {
+            literal: cx.const_eval_literal(&lit.node, expr_ty, lit.span, false),
+        },
 
         hir::ExprBinary(op, ref lhs, ref rhs) => {
             if cx.tables().is_method_call(expr) {
@@ -400,9 +402,10 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
             if cx.tables().is_method_call(expr) {
                 overloaded_operator(cx, expr, vec![arg.to_ref()])
             } else {
-                // FIXME runtime-overflow
-                if let hir::ExprLit(_) = arg.node {
-                    ExprKind::Literal { literal: cx.const_eval_literal(expr) }
+                if let hir::ExprLit(ref lit) = arg.node {
+                    ExprKind::Literal {
+                        literal: cx.const_eval_literal(&lit.node, expr_ty, lit.span, true),
+                    }
                 } else {
                     ExprKind::Unary {
                         op: UnOp::Neg,
@@ -509,8 +512,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(&ty::Const { val: ConstVal::Integral(ConstInt::Usize(u)), .. }) => u,
-                Ok(other) => bug!("constant evaluation of repeat count yielded {:?}", other),
+                Ok(cv) => cv.val.unwrap_usize(cx.tcx),
                 Err(s) => cx.fatal_const_eval_err(&s, c.span, "expression")
             };
 
@@ -634,8 +636,8 @@ fn method_callee<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
         span: expr.span,
         kind: ExprKind::Literal {
             literal: Literal::Value {
-                value: cx.tcx.mk_const(ty::Const {
-                    val: ConstVal::Function(def_id, substs),
+                value: cx.tcx().mk_const(ty::Const {
+                    val: const_fn(cx.tcx, def_id, substs),
                     ty
                 }),
             },
@@ -675,6 +677,28 @@ fn convert_arm<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, arm: &'tcx hir::Arm)
     }
 }
 
+fn const_fn<'a, 'gcx, 'tcx>(
+    tcx: TyCtxt<'a, 'gcx, 'tcx>,
+    def_id: DefId,
+    substs: &'tcx Substs<'tcx>,
+) -> ConstVal<'tcx> {
+    if tcx.sess.opts.debugging_opts.miri {
+        /*
+        let inst = ty::Instance::new(def_id, substs);
+        let ptr = tcx
+            .interpret_interner
+            .borrow_mut()
+            .create_fn_alloc(inst);
+        let ptr = MemoryPointer::new(AllocId(ptr), 0);
+        ConstVal::Value(Value::ByVal(PrimVal::Ptr(ptr)))
+        */
+        // ZST function type
+        ConstVal::Value(Value::ByVal(PrimVal::Undef))
+    } else {
+        ConstVal::Function(def_id, substs)
+    }
+}
+
 fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                                      expr: &'tcx hir::Expr,
                                      def: Def)
@@ -688,7 +712,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
         Def::VariantCtor(def_id, CtorKind::Fn) => ExprKind::Literal {
             literal: Literal::Value {
                 value: cx.tcx.mk_const(ty::Const {
-                    val: ConstVal::Function(def_id, substs),
+                    val: const_fn(cx.tcx.global_tcx(), def_id, substs),
                     ty: cx.tables().node_id_to_type(expr.hir_id)
                 }),
             },
index 44c413561175e768aff88d45dd257ad34c792ce5..7ebed0bbddbf581996ec01c4f7b2c18b0b6bcaae 100644 (file)
@@ -17,7 +17,6 @@
 use hair::*;
 
 use rustc::middle::const_val::{ConstEvalErr, ConstVal};
-use rustc_const_eval::ConstContext;
 use rustc_data_structures::indexed_vec::Idx;
 use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::hir::map::blocks::FnLikeNode;
@@ -32,6 +31,7 @@
 use rustc::hir;
 use rustc_const_math::{ConstInt, ConstUsize};
 use rustc_data_structures::sync::Lrc;
+use rustc::mir::interpret::{Value, PrimVal};
 
 #[derive(Clone)]
 pub struct Cx<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
@@ -119,7 +119,11 @@ pub fn usize_literal(&mut self, value: u64) -> Literal<'tcx> {
             Ok(val) => {
                 Literal::Value {
                     value: self.tcx.mk_const(ty::Const {
-                        val: ConstVal::Integral(ConstInt::Usize(val)),
+                        val: if self.tcx.sess.opts.debugging_opts.miri {
+                            ConstVal::Value(Value::ByVal(PrimVal::Bytes(value as u128)))
+                        } else {
+                            ConstVal::Integral(ConstInt::Usize(val))
+                        },
                         ty: self.tcx.types.usize
                     })
                 }
@@ -139,7 +143,11 @@ pub fn unit_ty(&mut self) -> Ty<'tcx> {
     pub fn true_literal(&mut self) -> Literal<'tcx> {
         Literal::Value {
             value: self.tcx.mk_const(ty::Const {
-                val: ConstVal::Bool(true),
+                val: if self.tcx.sess.opts.debugging_opts.miri {
+                    ConstVal::Value(Value::ByVal(PrimVal::Bytes(1)))
+                } else {
+                    ConstVal::Bool(true)
+                },
                 ty: self.tcx.types.bool
             })
         }
@@ -148,20 +156,161 @@ pub fn true_literal(&mut self) -> Literal<'tcx> {
     pub fn false_literal(&mut self) -> Literal<'tcx> {
         Literal::Value {
             value: self.tcx.mk_const(ty::Const {
-                val: ConstVal::Bool(false),
+                val: if self.tcx.sess.opts.debugging_opts.miri {
+                    ConstVal::Value(Value::ByVal(PrimVal::Bytes(0)))
+                } else {
+                    ConstVal::Bool(false)
+                },
                 ty: self.tcx.types.bool
             })
         }
     }
 
-    pub fn const_eval_literal(&mut self, e: &hir::Expr) -> Literal<'tcx> {
+    pub fn const_eval_literal(
+        &mut self,
+        lit: &'tcx ast::LitKind,
+        ty: Ty<'tcx>,
+        sp: Span,
+        neg: bool,
+    ) -> Literal<'tcx> {
         let tcx = self.tcx.global_tcx();
-        let const_cx = ConstContext::new(tcx,
-                                         self.param_env.and(self.identity_substs),
-                                         self.tables());
-        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")
+
+        let mut repr_ty = ty;
+        if let ty::TyAdt(adt, _) = ty.sty {
+            if adt.is_enum() {
+                repr_ty = adt.repr.discr_type().to_ty(tcx)
+            }
+        }
+
+        let parse_float = |num: &str, fty| -> ConstFloat {
+            ConstFloat::from_str(num, fty).unwrap_or_else(|_| {
+                // FIXME(#31407) this is only necessary because float parsing is buggy
+                tcx.sess.span_fatal(sp, "could not evaluate float literal (see issue #31407)");
+            })
+        };
+
+        if tcx.sess.opts.debugging_opts.miri {
+            use rustc::mir::interpret::*;
+            let lit = match *lit {
+                LitKind::Str(ref s, _) => {
+                    let s = s.as_str();
+                    let id = self.tcx.allocate_cached(s.as_bytes());
+                    let ptr = MemoryPointer::new(AllocId(id), 0);
+                    Value::ByValPair(
+                        PrimVal::Ptr(ptr),
+                        PrimVal::from_u128(s.len() as u128),
+                    )
+                },
+                LitKind::ByteStr(ref data) => {
+                    let id = self.tcx.allocate_cached(data);
+                    let ptr = MemoryPointer::new(AllocId(id), 0);
+                    Value::ByVal(PrimVal::Ptr(ptr))
+                },
+                LitKind::Byte(n) => Value::ByVal(PrimVal::Bytes(n as u128)),
+                LitKind::Int(n, _) if neg => {
+                    let n = n as i128;
+                    let n = n.overflowing_neg().0;
+                    Value::ByVal(PrimVal::Bytes(n as u128))
+                },
+                LitKind::Int(n, _) => Value::ByVal(PrimVal::Bytes(n)),
+                LitKind::Float(n, fty) => {
+                    let n = n.as_str();
+                    let mut f = parse_float(&n, fty);
+                    if neg {
+                        f = -f;
+                    }
+                    let bits = f.bits;
+                    Value::ByVal(PrimVal::Bytes(bits))
+                }
+                LitKind::FloatUnsuffixed(n) => {
+                    let fty = match ty.sty {
+                        ty::TyFloat(fty) => fty,
+                        _ => bug!()
+                    };
+                    let n = n.as_str();
+                    let mut f = parse_float(&n, fty);
+                    if neg {
+                        f = -f;
+                    }
+                    let bits = f.bits;
+                    Value::ByVal(PrimVal::Bytes(bits))
+                }
+                LitKind::Bool(b) => Value::ByVal(PrimVal::Bytes(b as u128)),
+                LitKind::Char(c) => Value::ByVal(PrimVal::Bytes(c as u128)),
+            };
+            return Literal::Value {
+                value: self.tcx.mk_const(ty::Const {
+                    val: Value(lit),
+                    ty,
+                }),
+            };
+        }
+
+        use syntax::ast::*;
+        use syntax::ast::LitIntType::*;
+        use rustc::middle::const_val::ConstVal::*;
+        use rustc_const_math::ConstInt::*;
+        use rustc::ty::util::IntTypeExt;
+        use rustc::middle::const_val::ByteArray;
+        use rustc_const_math::ConstFloat;
+
+        let lit = match *lit {
+            LitKind::Str(ref s, _) => Ok(Str(s.as_str())),
+            LitKind::ByteStr(ref data) => {
+                let data: &'tcx [u8] = data;
+                Ok(ByteStr(ByteArray { data }))
+            },
+            LitKind::Byte(n) => Ok(Integral(U8(n))),
+            LitKind::Int(n, hint) => {
+                match (&repr_ty.sty, hint) {
+                    (&ty::TyInt(ity), _) |
+                    (_, Signed(ity)) => {
+                        let mut n = n as i128;
+                        if neg {
+                            n = n.overflowing_neg().0;
+                        }
+                        Ok(Integral(ConstInt::new_signed_truncating(n,
+                            ity, tcx.sess.target.isize_ty)))
+                    }
+                    (&ty::TyUint(uty), _) |
+                    (_, Unsigned(uty)) => {
+                        Ok(Integral(ConstInt::new_unsigned_truncating(n,
+                            uty, tcx.sess.target.usize_ty)))
+                    }
+                    _ => bug!()
+                }
+            }
+            LitKind::Float(n, fty) => {
+                let mut f = parse_float(&n.as_str(), fty);
+                if neg {
+                    f = -f;
+                }
+                Ok(ConstVal::Float(f))
+            }
+            LitKind::FloatUnsuffixed(n) => {
+                let fty = match ty.sty {
+                    ty::TyFloat(fty) => fty,
+                    _ => bug!()
+                };
+                let mut f = parse_float(&n.as_str(), fty);
+                if neg {
+                    f = -f;
+                }
+                Ok(ConstVal::Float(f))
+            }
+            LitKind::Bool(b) => Ok(Bool(b)),
+            LitKind::Char(c) => Ok(Char(c)),
+        };
+
+        match lit {
+            Ok(value) => Literal::Value { value: self.tcx.mk_const(ty::Const {
+                val: value,
+                ty,
+            }) },
+            Err(kind) => self.fatal_const_eval_err(&ConstEvalErr {
+                span: sp,
+                kind,
+            }, sp, "expression")
         }
     }
 
@@ -203,7 +352,12 @@ pub fn trait_method(&mut self,
                 return (method_ty,
                         Literal::Value {
                             value: self.tcx.mk_const(ty::Const {
-                                val: ConstVal::Function(item.def_id, substs),
+                                val: if self.tcx.sess.opts.debugging_opts.miri {
+                                    // ZST function type
+                                    ConstVal::Value(Value::ByVal(PrimVal::Undef))
+                                } else {
+                                    ConstVal::Function(item.def_id, substs)
+                                },
                                 ty: method_ty
                             }),
                         });
index bc555368f0f5fb95d460470537010de9ebf43c1e..ec8215fb64c38f25020a95a2d7ea3cd20e03bb7f 100644 (file)
 use syntax::codemap::Span;
 
 use rustc::mir::interpret::{EvalResult, EvalError, EvalErrorKind, GlobalId, Value, MemoryPointer, Pointer, PrimVal};
-use super::{Place, EvalContext, StackPopCleanup, ValTy};
+use super::{Place, EvalContext, StackPopCleanup, ValTy, HasMemory};
 
 use rustc_const_math::ConstInt;
 
 use std::fmt;
 use std::error::Error;
 
-
 pub fn mk_eval_cx<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     instance: Instance<'tcx>,
@@ -45,7 +44,7 @@ pub fn eval_body<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     instance: Instance<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
-) -> EvalResult<'tcx, (Pointer, Ty<'tcx>)> {
+) -> EvalResult<'tcx, (Value, Pointer, Ty<'tcx>)> {
     debug!("eval_body: {:?}, {:?}", instance, param_env);
     let limits = super::ResourceLimits::default();
     let mut ecx = EvalContext::new(tcx, param_env, limits, CompileTimeEvaluator, ());
@@ -82,7 +81,13 @@ pub fn eval_body<'a, 'tcx>(
         while ecx.step()? {}
     }
     let alloc = tcx.interpret_interner.borrow().get_cached(cid).expect("global not cached");
-    Ok((MemoryPointer::new(alloc, 0).into(), instance_ty))
+    let align = ecx.layout_of(instance_ty)?.align;
+    let ptr = MemoryPointer::new(alloc, 0).into();
+    let value = match ecx.try_read_value(ptr, align, instance_ty)? {
+        Some(val) => val,
+        _ => Value::ByRef(ptr, align),
+    };
+    Ok((value, ptr, instance_ty))
 }
 
 pub fn eval_body_as_integer<'a, 'tcx>(
@@ -90,11 +95,9 @@ pub fn eval_body_as_integer<'a, 'tcx>(
     param_env: ty::ParamEnv<'tcx>,
     instance: Instance<'tcx>,
 ) -> EvalResult<'tcx, ConstInt> {
-    let ptr_ty = eval_body(tcx, instance, param_env);
-    let (ptr, ty) = ptr_ty?;
-    let ecx = mk_eval_cx(tcx, instance, param_env)?;
-    let prim = match ecx.try_read_value(ptr, ecx.layout_of(ty)?.align, ty)? {
-        Some(Value::ByVal(prim)) => prim.to_bytes()?,
+    let (value, _, ty) = eval_body(tcx, instance, param_env)?;
+    let prim = match value {
+        Value::ByVal(prim) => prim.to_bytes()?,
         _ => return err!(TypeNotPrimitive(ty)),
     };
     use syntax::ast::{IntTy, UintTy};
@@ -133,7 +136,7 @@ pub fn eval_body_as_integer<'a, 'tcx>(
 
 impl<'tcx> Into<EvalError<'tcx>> for ConstEvalError {
     fn into(self) -> EvalError<'tcx> {
-        EvalErrorKind::MachineError(Box::new(self)).into()
+        EvalErrorKind::MachineError(self.to_string()).into()
     }
 }
 
@@ -193,7 +196,6 @@ fn eval_fn_call<'a>(
         let mir = match ecx.load_mir(instance.def) {
             Ok(mir) => mir,
             Err(EvalError { kind: EvalErrorKind::NoMirFor(path), .. }) => {
-                // some simple things like `malloc` might get accepted in the future
                 return Err(
                     ConstEvalError::NeedsRfc(format!("calling extern function `{}`", path))
                         .into(),
@@ -302,6 +304,70 @@ fn global_item_with_linkage<'a>(
     }
 }
 
+pub fn const_val_field<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    key: ty::ParamEnvAnd<'tcx, (ty::Instance<'tcx>, mir::Field, Value, Ty<'tcx>)>,
+) -> ::rustc::middle::const_val::EvalResult<'tcx> {
+    trace!("const_val_field: {:#?}", key);
+    match const_val_field_inner(tcx, key) {
+        Ok((field, ty)) => Ok(tcx.mk_const(ty::Const {
+            val: ConstVal::Value(field),
+            ty,
+        })),
+        Err(err) => Err(ConstEvalErr {
+            span: tcx.def_span(key.value.0.def_id()),
+            kind: err.into(),
+        }),
+    }
+}
+
+fn const_val_field_inner<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    key: ty::ParamEnvAnd<'tcx, (ty::Instance<'tcx>, mir::Field, Value, Ty<'tcx>)>,
+) -> ::rustc::mir::interpret::EvalResult<'tcx, (Value, Ty<'tcx>)> {
+    trace!("const_val_field: {:#?}", key);
+    let (instance, field, value, ty) = key.value;
+    let mut ecx = mk_eval_cx(tcx, instance, key.param_env).unwrap();
+    let (mut field, ty) = match value {
+        Value::ByValPair(..) | Value::ByVal(_) => ecx.read_field(value, field, ty)?.expect("const_val_field on non-field"),
+        Value::ByRef(ptr, align) => {
+            let place = Place::from_primval_ptr(ptr, align);
+            let layout = ecx.layout_of(ty)?;
+            let (place, layout) = ecx.place_field(place, field, layout)?;
+            let (ptr, align) = place.to_ptr_align();
+            (Value::ByRef(ptr, align), layout.ty)
+        }
+    };
+    if let Value::ByRef(ptr, align) = field {
+        if let Some(val) = ecx.try_read_value(ptr, align, ty)? {
+            field = val;
+        }
+    }
+    Ok((field, ty))
+}
+
+pub fn const_discr<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    key: ty::ParamEnvAnd<'tcx, (ty::Instance<'tcx>, Value, Ty<'tcx>)>,
+) -> EvalResult<'tcx, u128> {
+    trace!("const_discr: {:#?}", key);
+    let (instance, value, ty) = key.value;
+    let mut ecx = mk_eval_cx(tcx, instance, key.param_env).unwrap();
+    let (ptr, align) = match value {
+        Value::ByValPair(..) | Value::ByVal(_) => {
+            let layout = ecx.layout_of(ty)?;
+            use super::MemoryKind;
+            let ptr = ecx.memory.allocate(layout.size.bytes(), layout.align, Some(MemoryKind::Stack))?;
+            let ptr: Pointer = ptr.into();
+            ecx.write_value_to_ptr(value, ptr, layout.align, ty)?;
+            (ptr, layout.align)
+        },
+        Value::ByRef(ptr, align) => (ptr, align),
+    };
+    let place = Place::from_primval_ptr(ptr, align);
+    ecx.read_discriminant_value(place, ty)
+}
+
 pub fn const_eval_provider<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     key: ty::ParamEnvAnd<'tcx, (DefId, &'tcx Substs<'tcx>)>,
@@ -340,35 +406,48 @@ pub fn const_eval_provider<'a, 'tcx>(
         return Err(ConstEvalErr { span: body.value.span, kind: TypeckError })
     }
 
+
+    let instance = ty::Instance::new(def_id, substs);
+    if tcx.sess.opts.debugging_opts.miri {
+        return match ::interpret::eval_body(tcx, instance, key.param_env) {
+            Ok((miri_value, _, miri_ty)) => Ok(tcx.mk_const(ty::Const {
+                val: ConstVal::Value(miri_value),
+                ty: miri_ty,
+            })),
+            Err(err) => {
+                Err(ConstEvalErr { span: body.value.span, kind: err.into() })
+            }
+        };
+    }
+
     trace!("running old const eval");
     let old_result = ConstContext::new(tcx, key.param_env.and(substs), tables).eval(&body.value);
     trace!("old const eval produced {:?}", old_result);
-    if tcx.sess.opts.debugging_opts.miri {
-        let instance = ty::Instance::new(def_id, substs);
-        trace!("const eval instance: {:?}, {:?}", instance, key.param_env);
-        let miri_result = ::interpret::eval_body(tcx, instance, key.param_env);
-        match (miri_result, old_result) {
-            (Err(err), Ok(ok)) => {
-                trace!("miri failed, ctfe returned {:?}", ok);
-                tcx.sess.span_warn(
-                    tcx.def_span(key.value.0),
-                    "miri failed to eval, while ctfe succeeded",
-                );
-                let ecx = mk_eval_cx(tcx, instance, key.param_env).unwrap();
-                let () = unwrap_miri(&ecx, Err(err));
-                Ok(ok)
-            },
-            (_, Err(err)) => Err(err),
-            (Ok((miri_val, miri_ty)), Ok(ctfe)) => {
-                let mut ecx = mk_eval_cx(tcx, instance, key.param_env).unwrap();
-                let layout = ecx.layout_of(miri_ty).unwrap();
-                let miri_place = Place::from_primval_ptr(miri_val, layout.align);
-                check_ctfe_against_miri(&mut ecx, miri_place, miri_ty, ctfe.val);
-                Ok(ctfe)
-            }
+    trace!("const eval instance: {:?}, {:?}", instance, key.param_env);
+    let miri_result = ::interpret::eval_body(tcx, instance, key.param_env);
+    match (miri_result, old_result) {
+        (Err(err), Ok(ok)) => {
+            trace!("miri failed, ctfe returned {:?}", ok);
+            tcx.sess.span_warn(
+                tcx.def_span(key.value.0),
+                "miri failed to eval, while ctfe succeeded",
+            );
+            let ecx = mk_eval_cx(tcx, instance, key.param_env).unwrap();
+            let () = unwrap_miri(&ecx, Err(err));
+            Ok(ok)
+        },
+        (Ok((value, _, ty)), Err(_)) => Ok(tcx.mk_const(ty::Const {
+            val: ConstVal::Value(value),
+            ty,
+        })),
+        (Err(_), Err(err)) => Err(err),
+        (Ok((_, miri_ptr, miri_ty)), Ok(ctfe)) => {
+            let mut ecx = mk_eval_cx(tcx, instance, key.param_env).unwrap();
+            let layout = ecx.layout_of(miri_ty).unwrap();
+            let miri_place = Place::from_primval_ptr(miri_ptr, layout.align);
+            check_ctfe_against_miri(&mut ecx, miri_place, miri_ty, ctfe.val);
+            Ok(ctfe)
         }
-    } else {
-        old_result
     }
 }
 
@@ -451,7 +530,7 @@ fn check_ctfe_against_miri<'a, 'tcx>(
             }
         },
         TyArray(elem_ty, n) => {
-            let n = n.val.to_const_int().unwrap().to_u64().unwrap();
+            let n = n.val.unwrap_u64();
             let vec: Vec<(ConstVal, Ty<'tcx>)> = match ctfe {
                 ConstVal::ByteStr(arr) => arr.data.iter().map(|&b| {
                     (ConstVal::Integral(ConstInt::U8(b)), ecx.tcx.types.u8)
index e9e8ccd03b10fd143453ae5f5a30d4c9d057bfcf..f37fb3072b5841c64abe3541dd5fcdbf6edd140f 100644 (file)
@@ -601,7 +601,7 @@ pub(super) fn eval_rvalue_into_place(
 
             Repeat(ref operand, _) => {
                 let (elem_ty, length) = match dest_ty.sty {
-                    ty::TyArray(elem_ty, n) => (elem_ty, n.val.to_const_int().unwrap().to_u64().unwrap()),
+                    ty::TyArray(elem_ty, n) => (elem_ty, n.val.unwrap_u64()),
                     _ => {
                         bug!(
                             "tried to assign array-repeat to non-array type {:?}",
@@ -1386,7 +1386,7 @@ fn unsize_into_ptr(
                 let ptr = self.into_ptr(src)?;
                 // u64 cast is from usize to u64, which is always good
                 let valty = ValTy {
-                    value: ptr.to_value_with_len(length.val.to_const_int().unwrap().to_u64().unwrap() ),
+                    value: ptr.to_value_with_len(length.val.unwrap_u64() ),
                     ty: dest_ty,
                 };
                 self.write_value(valty, dest)
index fee62c8a82e2f08a2895fb02949919143612cff4..a6ebdd45968fcd0913116ba57f26870be0c760fb 100644 (file)
@@ -18,6 +18,6 @@
 
 pub use self::memory::{Memory, MemoryKind, HasMemory};
 
-pub use self::const_eval::{eval_body_as_integer, eval_body, CompileTimeEvaluator, const_eval_provider};
+pub use self::const_eval::{eval_body_as_integer, eval_body, CompileTimeEvaluator, const_eval_provider, const_val_field, const_discr};
 
 pub use self::machine::Machine;
index 6ab1aec38b863cade1c7195ab072ee3771f1fcb8..b20540b00ceaefde5130e5393726b478c6b79e98 100644 (file)
@@ -248,10 +248,15 @@ pub fn unary_op<'tcx>(
         (Not, I64) => !(bytes as i64) as u128,
         (Not, I128) => !(bytes as i128) as u128,
 
+        (Neg, I8) if bytes == i8::min_value() as u128 => return err!(OverflowingMath),
         (Neg, I8) => -(bytes as i8) as u128,
+        (Neg, I16) if bytes == i16::min_value() as u128 => return err!(OverflowingMath),
         (Neg, I16) => -(bytes as i16) as u128,
+        (Neg, I32) if bytes == i32::min_value() as u128 => return err!(OverflowingMath),
         (Neg, I32) => -(bytes as i32) as u128,
+        (Neg, I64) if bytes == i64::min_value() as u128 => return err!(OverflowingMath),
         (Neg, I64) => -(bytes as i64) as u128,
+        (Neg, I128) if bytes == i128::min_value() as u128 => return err!(OverflowingMath),
         (Neg, I128) => -(bytes as i128) as u128,
 
         (Neg, F32) => (-bytes_to_f32(bytes)).bits,
index 701b7a07ac988f131f710cb6e8f0730b021d3344..c5e4eeab86709f69bd680bc13a14cf1f6c4355b4 100644 (file)
@@ -71,7 +71,7 @@ pub fn to_ptr(self) -> EvalResult<'tcx, MemoryPointer> {
 
     pub(super) fn elem_ty_and_len(self, ty: Ty<'tcx>) -> (Ty<'tcx>, u64) {
         match ty.sty {
-            ty::TyArray(elem, n) => (elem, n.val.to_const_int().unwrap().to_u64().unwrap() as u64),
+            ty::TyArray(elem, n) => (elem, n.val.unwrap_u64() as u64),
 
             ty::TySlice(elem) => {
                 match self {
@@ -115,6 +115,29 @@ pub fn try_read_place(
         }
     }
 
+    pub fn read_field(
+        &self,
+        base: Value,
+        field: mir::Field,
+        base_ty: Ty<'tcx>,
+    ) -> EvalResult<'tcx, Option<(Value, Ty<'tcx>)>> {
+        let base_layout = self.layout_of(base_ty)?;
+        let field_index = field.index();
+        let field = base_layout.field(self, field_index)?;
+        let offset = base_layout.fields.offset(field_index);
+        match base {
+            // the field covers the entire type
+            Value::ByValPair(..) |
+            Value::ByVal(_) if offset.bytes() == 0 && field.size == base_layout.size => Ok(Some((base, field.ty))),
+            // split fat pointers, 2 element tuples, ...
+            Value::ByValPair(a, b) if base_layout.fields.count() == 2 => {
+                let val = [a, b][field_index];
+                Ok(Some((Value::ByVal(val), field.ty)))
+            },
+            _ => Ok(None),
+        }
+    }
+
     fn try_read_place_projection(
         &mut self,
         proj: &mir::PlaceProjection<'tcx>,
@@ -126,23 +149,7 @@ fn try_read_place_projection(
         };
         let base_ty = self.place_ty(&proj.base);
         match proj.elem {
-            Field(field, _) => {
-                let base_layout = self.layout_of(base_ty)?;
-                let field_index = field.index();
-                let field = base_layout.field(&self, field_index)?;
-                let offset = base_layout.fields.offset(field_index);
-                match base {
-                    // the field covers the entire type
-                    Value::ByValPair(..) |
-                    Value::ByVal(_) if offset.bytes() == 0 && field.size == base_layout.size => Ok(Some(base)),
-                    // split fat pointers, 2 element tuples, ...
-                    Value::ByValPair(a, b) if base_layout.fields.count() == 2 => {
-                        let val = [a, b][field_index];
-                        Ok(Some(Value::ByVal(val)))
-                    },
-                    _ => Ok(None),
-                }
-            },
+            Field(field, _) => Ok(self.read_field(base, field, base_ty)?.map(|(f, _)| f)),
             // The NullablePointer cases should work fine, need to take care for normal enums
             Downcast(..) |
             Subslice { .. } |
index 606bda51edb1fdfe304a01c4eada0f125c0b7abe..c18cf6d9f96b9bbd63833c8eba7ecb1dcd4bb72b 100644 (file)
@@ -45,8 +45,8 @@ pub(super) fn eval_terminator(
                 // Branch to the `otherwise` case by default, if no match is found.
                 let mut target_block = targets[targets.len() - 1];
 
-                for (index, const_int) in values.iter().enumerate() {
-                    let prim = PrimVal::Bytes(const_int.to_u128_unchecked());
+                for (index, &const_int) in values.iter().enumerate() {
+                    let prim = PrimVal::Bytes(const_int);
                     if discr_prim.to_bytes()? == prim.to_bytes()? {
                         target_block = targets[index];
                         break;
index 38b8ffc6b9c806f6a3b04197b80f575058b26856..1f7f1237ba7894901e671f36ed1a42584dad5605 100644 (file)
@@ -314,7 +314,7 @@ pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String) {
                 output.push('[');
                 self.push_type_name(inner_type, output);
                 write!(output, "; {}",
-                    len.val.to_const_int().unwrap().to_u64().unwrap()).unwrap();
+                    len.val.unwrap_u64()).unwrap();
                 output.push(']');
             },
             ty::TySlice(inner_type) => {
index e6ebdd3d6c16702fc2c839f7d23a600bf6bac105..11dded1d3f075b57059359ca7cd31deae8901bff 100644 (file)
@@ -17,6 +17,7 @@
 use rustc::ty::subst::{Kind, Subst, Substs};
 use rustc::ty::maps::Providers;
 use rustc_const_math::{ConstInt, ConstUsize};
+use rustc::mir::interpret::{Value, PrimVal};
 
 use rustc_data_structures::indexed_vec::{IndexVec, Idx};
 
@@ -303,7 +304,7 @@ fn build_clone_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     match self_ty.sty {
         _ if is_copy => builder.copy_shim(),
         ty::TyArray(ty, len) => {
-            let len = len.val.to_const_int().unwrap().to_u64().unwrap();
+            let len = len.val.unwrap_u64();
             builder.array_shim(dest, src, ty, len)
         }
         ty::TyClosure(def_id, substs) => {
@@ -443,7 +444,12 @@ fn make_clone_call(
             ty: func_ty,
             literal: Literal::Value {
                 value: tcx.mk_const(ty::Const {
-                    val: ConstVal::Function(self.def_id, substs),
+                    val: if tcx.sess.opts.debugging_opts.miri {
+                        // ZST function type
+                        ConstVal::Value(Value::ByVal(PrimVal::Undef))
+                    } else {
+                        ConstVal::Function(self.def_id, substs)
+                    },
                     ty: func_ty
                 }),
             },
@@ -501,13 +507,20 @@ fn loop_header(
     }
 
     fn make_usize(&self, value: u64) -> Box<Constant<'tcx>> {
-        let value = ConstUsize::new(value, self.tcx.sess.target.usize_ty).unwrap();
         box Constant {
             span: self.span,
             ty: self.tcx.types.usize,
             literal: Literal::Value {
                 value: self.tcx.mk_const(ty::Const {
-                    val: ConstVal::Integral(ConstInt::Usize(value)),
+                    val: if self.tcx.sess.opts.debugging_opts.miri {
+                        ConstVal::Value(Value::ByVal(PrimVal::Bytes(value.into())))
+                    } else {
+                        let value = ConstUsize::new(
+                            value,
+                            self.tcx.sess.target.usize_ty,
+                        ).unwrap();
+                        ConstVal::Integral(ConstInt::Usize(value))
+                    },
                     ty: self.tcx.types.usize,
                 })
             }
@@ -739,8 +752,12 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 ty,
                 literal: Literal::Value {
                     value: tcx.mk_const(ty::Const {
-                        val: ConstVal::Function(def_id,
-                            Substs::identity_for_item(tcx, def_id)),
+                        val: if tcx.sess.opts.debugging_opts.miri {
+                            // ZST function type
+                            ConstVal::Value(Value::ByVal(PrimVal::Undef))
+                        } else {
+                            ConstVal::Function(def_id, Substs::identity_for_item(tcx, def_id))
+                        },
                         ty
                     }),
                 },
index 04ebaa031fe5a305548574865e2c1724fe61dac1..ec3edb1e0680e58414abe86d4ccd1773c4eda013 100644 (file)
@@ -80,6 +80,7 @@
 use transform::no_landing_pads::no_landing_pads;
 use dataflow::{do_dataflow, DebugFormatted, state_for_location};
 use dataflow::{MaybeStorageLive, HaveBeenBorrowedLocals};
+use rustc::mir::interpret::{Value, PrimVal};
 
 pub struct StateTransform;
 
@@ -181,7 +182,11 @@ fn set_state(&self, state_disc: u32, source_info: SourceInfo) -> Statement<'tcx>
             ty: self.tcx.types.u32,
             literal: Literal::Value {
                 value: self.tcx.mk_const(ty::Const {
-                    val: ConstVal::Integral(ConstInt::U32(state_disc)),
+                    val: if self.tcx.sess.opts.debugging_opts.miri {
+                        ConstVal::Value(Value::ByVal(PrimVal::Bytes(state_disc.into())))
+                    } else {
+                        ConstVal::Integral(ConstInt::U32(state_disc))
+                    },
                     ty: self.tcx.types.u32
                 }),
             },
@@ -534,7 +539,7 @@ fn insert_switch<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let switch = TerminatorKind::SwitchInt {
         discr: Operand::Copy(transform.make_field(transform.state_field, tcx.types.u32)),
         switch_ty: tcx.types.u32,
-        values: Cow::from(cases.iter().map(|&(i, _)| ConstInt::U32(i)).collect::<Vec<_>>()),
+        values: Cow::from(cases.iter().map(|&(i, _)| i.into()).collect::<Vec<_>>()),
         targets: cases.iter().map(|&(_, d)| d).chain(once(default_block)).collect(),
     };
 
index 64c702b99cdb3940350a841bef58b4717fa5ea70..b8a0e0f89073dc09c263f3d08e3bf8c96b778735 100644 (file)
@@ -207,6 +207,13 @@ fn should_inline(&self,
             return false;
         }
 
+        // Do not inline {u,i}128 lang items, trans const eval depends
+        // on detecting calls to these lang items and intercepting them
+        if tcx.is_binop_lang_item(callsite.callee).is_some() {
+            debug!("    not inlining 128bit integer lang item");
+            return false;
+        }
+
         let trans_fn_attrs = tcx.trans_fn_attrs(callsite.callee);
 
         let hinted = match trans_fn_attrs.inline {
index 8f5831270d6e5afa94af754ef71f2f7e24914c61..88618122e4f1137d5e0fe7b8b90849fc2d0cf640 100644 (file)
@@ -690,7 +690,7 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
                             _ => false
                         }
                     } else if let ty::TyArray(_, len) = ty.sty {
-                        len.val.to_const_int().unwrap().to_u64().unwrap() == 0 &&
+                        len.val.unwrap_u64() == 0 &&
                             self.mode == Mode::Fn
                     } else {
                         false
index 41089f567bd710c65d99219109fc428c2615bec5..ca7f573b58a4775840c065c55006ed5d7eeb0521 100644 (file)
@@ -40,10 +40,10 @@ fn run_pass<'a, 'tcx>(&self,
                 TerminatorKind::SwitchInt { discr: Operand::Constant(box Constant {
                     literal: Literal::Value { ref value }, ..
                 }), ref values, ref targets, .. } => {
-                    if let Some(ref constint) = value.val.to_const_int() {
+                    if let Some(constint) = value.val.to_u128() {
                         let (otherwise, targets) = targets.split_last().unwrap();
                         let mut ret = TerminatorKind::Goto { target: *otherwise };
-                        for (v, t) in values.iter().zip(targets.iter()) {
+                        for (&v, t) in values.iter().zip(targets.iter()) {
                             if v == constint {
                                 ret = TerminatorKind::Goto { target: *t };
                                 break;
index e2feb0ed39054c839c26f0e126b91dc0432ba608..77ef2c20117f1ecb215f2fba658a292e4af42df5 100644 (file)
 use std::fmt;
 use rustc::hir;
 use rustc::mir::*;
-use rustc::middle::const_val::{ConstInt, ConstVal};
+use rustc::middle::const_val::ConstVal;
 use rustc::middle::lang_items;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::subst::{Kind, Substs};
 use rustc::ty::util::IntTypeExt;
 use rustc_data_structures::indexed_vec::Idx;
 use util::patch::MirPatch;
+use rustc::mir::interpret::{Value, PrimVal};
 
 use std::{iter, u32};
 
@@ -425,7 +426,7 @@ fn open_drop_for_multivariant(&mut self, adt: &'tcx ty::AdtDef,
                     variant_path,
                     &adt.variants[variant_index],
                     substs);
-                values.push(discr);
+                values.push(discr.to_u128().unwrap());
                 if let Unwind::To(unwind) = unwind {
                     // We can't use the half-ladder from the original
                     // drop ladder, because this breaks the
@@ -480,7 +481,7 @@ fn open_drop_for_multivariant(&mut self, adt: &'tcx ty::AdtDef,
     fn adt_switch_block(&mut self,
                         adt: &'tcx ty::AdtDef,
                         blocks: Vec<BasicBlock>,
-                        values: &[ConstInt],
+                        values: &[u128],
                         succ: BasicBlock,
                         unwind: Unwind)
                         -> BasicBlock {
@@ -803,7 +804,7 @@ fn open_drop<'a>(&mut self) -> BasicBlock {
                 self.complete_drop(Some(DropFlagMode::Deep), succ, unwind)
             }
             ty::TyArray(ety, size) => self.open_drop_for_array(
-                ety, size.val.to_const_int().and_then(|v| v.to_u64())),
+                ety, size.val.to_u128().map(|i| i as u64)),
             ty::TySlice(ety) => self.open_drop_for_array(ety, None),
 
             _ => bug!("open drop from non-ADT `{:?}`", ty)
@@ -949,7 +950,11 @@ fn constant_usize(&self, val: u16) -> Operand<'tcx> {
             ty: self.tcx().types.usize,
             literal: Literal::Value {
                 value: self.tcx().mk_const(ty::Const {
-                    val: ConstVal::Integral(self.tcx().const_usize(val)),
+                    val: if self.tcx().sess.opts.debugging_opts.miri {
+                        ConstVal::Value(Value::ByVal(PrimVal::Bytes(val.into())))
+                    } else {
+                        ConstVal::Integral(self.tcx().const_usize(val))
+                    },
                     ty: self.tcx().types.usize
                 })
             }
index b93b759fdf869ecc4dd6159265f2c72f17b237ad..8153c3c8493ff0ec4651f1ad5c4e876e1221aa59 100644 (file)
@@ -129,6 +129,9 @@ fn const_cx(&self) -> ConstContext<'a, 'gcx> {
     }
 
     fn check_const_eval(&self, expr: &'gcx hir::Expr) {
+        if self.tcx.sess.opts.debugging_opts.miri {
+            return;
+        }
         if let Err(err) = self.const_cx().eval(expr) {
             match err.kind {
                 UnimplementedConstVal(_) => {}
@@ -220,23 +223,24 @@ fn visit_pat(&mut self, p: &'tcx hir::Pat) {
                 self.check_const_eval(lit);
             }
             PatKind::Range(ref start, ref end, RangeEnd::Excluded) => {
-                match self.const_cx().compare_lit_exprs(p.span, start, end) {
-                    Ok(Ordering::Less) => {}
-                    Ok(Ordering::Equal) |
-                    Ok(Ordering::Greater) => {
+                match self.const_cx().compare_lit_exprs(start, end) {
+                    Ok(Some(Ordering::Less)) => {}
+                    Ok(Some(Ordering::Equal)) |
+                    Ok(Some(Ordering::Greater)) => {
                         span_err!(self.tcx.sess,
                                   start.span,
                                   E0579,
                                   "lower range bound must be less than upper");
                     }
+                    Ok(None) => bug!("ranges must be char or int"),
                     Err(ErrorReported) => {}
                 }
             }
             PatKind::Range(ref start, ref end, RangeEnd::Included) => {
-                match self.const_cx().compare_lit_exprs(p.span, start, end) {
-                    Ok(Ordering::Less) |
-                    Ok(Ordering::Equal) => {}
-                    Ok(Ordering::Greater) => {
+                match self.const_cx().compare_lit_exprs(start, end) {
+                    Ok(Some(Ordering::Less)) |
+                    Ok(Some(Ordering::Equal)) => {}
+                    Ok(Some(Ordering::Greater)) => {
                         let mut err = struct_span_err!(
                             self.tcx.sess,
                             start.span,
@@ -252,6 +256,7 @@ fn visit_pat(&mut self, p: &'tcx hir::Pat) {
                         }
                         err.emit();
                     }
+                    Ok(None) => bug!("ranges must be char or int"),
                     Err(ErrorReported) => {}
                 }
             }
@@ -308,7 +313,7 @@ fn visit_expr(&mut self, ex: &'tcx hir::Expr) {
             self.promotable = false;
         }
 
-        if self.in_fn && self.promotable {
+        if self.in_fn && self.promotable && !self.tcx.sess.opts.debugging_opts.miri {
             match self.const_cx().eval(ex) {
                 Ok(_) => {}
                 Err(ConstEvalErr { kind: UnimplementedConstVal(_), .. }) |
index 3708f6f6ec4fcf0124c11a8c762d0d5d592c3335..314b8c59df5ab95566f70de93ac398a8b83bec74 100644 (file)
@@ -195,7 +195,7 @@ pub fn unsized_info<'cx, 'tcx>(cx: &CodegenCx<'cx, 'tcx>,
     let (source, target) = cx.tcx.struct_lockstep_tails(source, target);
     match (&source.sty, &target.sty) {
         (&ty::TyArray(_, len), &ty::TySlice(_)) => {
-            C_usize(cx, len.val.to_const_int().unwrap().to_u64().unwrap())
+            C_usize(cx, len.val.unwrap_u64())
         }
         (&ty::TyDynamic(..), &ty::TyDynamic(..)) => {
             // For now, upcasts are limited to changes in marker
index 2c430d03c968ec02d46b05ff75b5513c3dd06200..0fe425fb7ea1ecd4f36bb91941e61e916154ed84 100644 (file)
@@ -276,7 +276,7 @@ fn fixed_vec_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
 
     let upper_bound = match array_or_slice_type.sty {
         ty::TyArray(_, len) => {
-            len.val.to_const_int().unwrap().to_u64().unwrap() as c_longlong
+            len.val.unwrap_u64() as c_longlong
         }
         _ => -1
     };
index 6490d109f2936454601a4639857280c5a0eef375..a88eb9ae354718eaa696d8c01bb8fbd3867e9c80 100644 (file)
@@ -97,7 +97,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
         ty::TyArray(inner_type, len) => {
             output.push('[');
             push_debuginfo_type_name(cx, inner_type, true, output);
-            output.push_str(&format!("; {}", len.val.to_const_int().unwrap().to_u64().unwrap()));
+            output.push_str(&format!("; {}", len.val.unwrap_u64()));
             output.push(']');
         },
         ty::TySlice(inner_type) => {
index f683703ce6d53403851dcb5567bd0fda34871dba..c88e39d7824c7213c1c2feee011e8fbf5adef56a 100644 (file)
@@ -17,6 +17,7 @@
 use rustc::mir::{self, Location, TerminatorKind, Literal};
 use rustc::mir::visit::{Visitor, PlaceContext};
 use rustc::mir::traversal;
+use rustc::mir::interpret::{Value, PrimVal};
 use rustc::ty;
 use rustc::ty::layout::LayoutOf;
 use type_of::LayoutLlvmExt;
@@ -109,15 +110,26 @@ fn visit_terminator_kind(&mut self,
                              block: mir::BasicBlock,
                              kind: &mir::TerminatorKind<'tcx>,
                              location: Location) {
-        match *kind {
+        let check = match *kind {
             mir::TerminatorKind::Call {
                 func: mir::Operand::Constant(box mir::Constant {
                     literal: Literal::Value {
-                        value: &ty::Const { val: ConstVal::Function(def_id, _), .. }, ..
+                        value: &ty::Const { val, ty }, ..
                     }, ..
                 }),
                 ref args, ..
-            } if Some(def_id) == self.fx.cx.tcx.lang_items().box_free_fn() => {
+            } => match val {
+                ConstVal::Function(def_id, _) => Some((def_id, args)),
+                ConstVal::Value(Value::ByVal(PrimVal::Undef)) => match ty.sty {
+                    ty::TyFnDef(did, _) => Some((did, args)),
+                    _ => None,
+                },
+                _ => None,
+            }
+            _ => None,
+        };
+        if let Some((def_id, args)) = check {
+            if Some(def_id) == self.cx.ccx.tcx().lang_items().box_free_fn() {
                 // box_free(x) shares with `drop x` the property that it
                 // is not guaranteed to be statically dominated by the
                 // definition of x, so x must always be in an alloca.
@@ -125,7 +137,6 @@ fn visit_terminator_kind(&mut self,
                     self.visit_place(place, PlaceContext::Drop, location);
                 }
             }
-            _ => {}
         }
 
         self.super_terminator_kind(block, kind, location);
index bb2a7840faee76e38b57d152e84991fd835948a9..239300c1ecf4e6df1e630918a65a92059886ef50 100644 (file)
@@ -10,7 +10,7 @@
 
 use llvm::{self, ValueRef, BasicBlockRef};
 use rustc::middle::lang_items;
-use rustc::middle::const_val::{ConstEvalErr, ConstInt, ErrKind};
+use rustc::middle::const_val::{ConstEvalErr, ErrKind};
 use rustc::ty::{self, TypeFoldable};
 use rustc::ty::layout::{self, LayoutOf};
 use rustc::traits;
@@ -196,17 +196,18 @@ fn trans_terminator(&mut self,
                 if switch_ty == bx.tcx().types.bool {
                     let lltrue = llblock(self, targets[0]);
                     let llfalse = llblock(self, targets[1]);
-                    if let [ConstInt::U8(0)] = values[..] {
+                    if let [0] = values[..] {
                         bx.cond_br(discr.immediate(), llfalse, lltrue);
                     } else {
+                        assert_eq!(&values[..], &[1]);
                         bx.cond_br(discr.immediate(), lltrue, llfalse);
                     }
                 } else {
                     let (otherwise, targets) = targets.split_last().unwrap();
                     let switch = bx.switch(discr.immediate(),
                                             llblock(self, *otherwise), values.len());
-                    for (value, target) in values.iter().zip(targets) {
-                        let val = Const::from_constint(bx.cx, value);
+                    for (&value, target) in values.iter().zip(targets) {
+                        let val = Const::from_bytes(bx.cx, value, switch_ty);
                         let llbb = llblock(self, *target);
                         bx.add_case(switch, val.llval, llbb)
                     }
index c853230b15ab7da78d1d33ecfd3fa4f545f06233..5bd5f19a57c63fbe671f1d7e0525fadffe1024e0 100644 (file)
@@ -16,6 +16,7 @@
 use rustc::infer::TransNormalize;
 use rustc::traits;
 use rustc::mir;
+use rustc::mir::interpret::{Value as MiriValue, PrimVal};
 use rustc::mir::tcx::PlaceTy;
 use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
 use rustc::ty::layout::{self, LayoutOf, Size};
@@ -38,6 +39,7 @@
 
 use syntax_pos::Span;
 use syntax::ast;
+use syntax::symbol::Symbol;
 
 use std::fmt;
 use std::ptr;
@@ -81,12 +83,46 @@ pub fn from_constint(cx: &CodegenCx<'a, 'tcx>, ci: &ConstInt) -> Const<'tcx> {
         Const { llval: llval, ty: ty }
     }
 
+    pub fn from_bytes(ccx: &CrateContext<'a, 'tcx>, b: u128, ty: Ty<'tcx>) -> Const<'tcx> {
+        let llval = match ty.sty {
+            ty::TyInt(ast::IntTy::I128) |
+            ty::TyUint(ast::UintTy::U128) => C_uint_big(Type::i128(ccx), b),
+            ty::TyInt(i) => C_int(Type::int_from_ty(ccx, i), b as i128 as i64),
+            ty::TyUint(u) => C_uint(Type::uint_from_ty(ccx, u), b as u64),
+            ty::TyBool => {
+                assert!(b <= 1);
+                C_bool(ccx, b == 1)
+            },
+            ty::TyChar => {
+                assert_eq!(b as u32 as u128, b);
+                let c = b as u32;
+                assert!(::std::char::from_u32(c).is_some());
+                C_uint(Type::char(ccx), c as u64)
+            },
+            ty::TyFloat(fty) => {
+                let llty = ccx.layout_of(ty).llvm_type(ccx);
+                let bits = match fty {
+                    ast::FloatTy::F32 => C_u32(ccx, b as u32),
+                    ast::FloatTy::F64 => C_u64(ccx, b as u64),
+                };
+                consts::bitcast(bits, llty)
+            },
+            ty::TyAdt(adt, _) if adt.is_enum() => {
+                use rustc::ty::util::IntTypeExt;
+                Const::from_bytes(ccx, b, adt.repr.discr_type().to_ty(ccx.tcx())).llval
+            },
+            _ => bug!("from_bytes({}, {})", b, ty),
+        };
+        Const { llval, ty }
+    }
+
     /// Translate ConstVal into a LLVM constant value.
     pub fn from_constval(cx: &CodegenCx<'a, 'tcx>,
                          cv: &ConstVal,
                          ty: Ty<'tcx>)
                          -> Const<'tcx> {
         let llty = cx.layout_of(ty).llvm_type(cx);
+        trace!("from_constval: {:#?}: {}", cv, ty);
         let val = match *cv {
             ConstVal::Float(v) => {
                 let bits = match v.ty {
@@ -108,7 +144,41 @@ pub fn from_constval(cx: &CodegenCx<'a, 'tcx>,
             ConstVal::Unevaluated(..) => {
                 bug!("MIR must not use `{:?}` (aggregates are expanded to MIR rvalues)", cv)
             }
-            ConstVal::Value(_) => unimplemented!(),
+            ConstVal::Value(MiriValue::ByRef(..)) => unimplemented!("{:#?}:{}", cv, ty),
+            ConstVal::Value(MiriValue::ByValPair(PrimVal::Ptr(ptr), PrimVal::Bytes(len))) => {
+                match ty.sty {
+                    ty::TyRef(_, ref tam) => match tam.ty.sty {
+                        ty::TyStr => {},
+                        _ => unimplemented!("non-str fat pointer: {:?}: {:?}", ptr, ty),
+                    },
+                    _ => unimplemented!("non-str fat pointer: {:?}: {:?}", ptr, ty),
+                }
+                let alloc = ccx
+                    .tcx()
+                    .interpret_interner
+                    .borrow()
+                    .get_alloc(ptr.alloc_id.0)
+                    .expect("miri alloc not found");
+                assert_eq!(len as usize as u128, len);
+                let slice = &alloc.bytes[(ptr.offset as usize)..][..(len as usize)];
+                let s = ::std::str::from_utf8(slice)
+                    .expect("non utf8 str from miri");
+                C_str_slice(ccx, Symbol::intern(s).as_str())
+            },
+            ConstVal::Value(MiriValue::ByValPair(..)) => unimplemented!(),
+            ConstVal::Value(MiriValue::ByVal(PrimVal::Bytes(b))) =>
+                return Const::from_bytes(ccx, b, ty),
+            ConstVal::Value(MiriValue::ByVal(PrimVal::Undef)) => C_undef(llty),
+            ConstVal::Value(MiriValue::ByVal(PrimVal::Ptr(ptr))) => {
+                let alloc = ccx
+                    .tcx()
+                    .interpret_interner
+                    .borrow()
+                    .get_alloc(ptr.alloc_id.0)
+                    .expect("miri alloc not found");
+                let data = &alloc.bytes[(ptr.offset as usize)..];
+                consts::addr_of(ccx, C_bytes(ccx, data), ccx.align_of(ty), "byte_str")
+            }
         };
 
         assert!(!ty.has_erasable_regions());
@@ -239,7 +309,7 @@ fn to_const(&self, span: Span) -> Const<'tcx> {
     pub fn len<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> ValueRef {
         match self.ty.sty {
             ty::TyArray(_, n) => {
-                C_usize(cx, n.val.to_const_int().unwrap().to_u64().unwrap())
+                C_usize(cx, n.val.unwrap_u64())
             }
             ty::TySlice(_) | ty::TyStr => {
                 assert!(self.llextra != ptr::null_mut());
@@ -316,7 +386,7 @@ fn trans(&mut self) -> Result<Const<'tcx>, ConstEvalErr<'tcx>> {
         let tcx = self.cx.tcx;
         let mut bb = mir::START_BLOCK;
 
-        // Make sure to evaluate all statemenets to
+        // Make sure to evaluate all statements to
         // report as many errors as we possibly can.
         let mut failure = Ok(());
 
@@ -392,6 +462,7 @@ fn trans(&mut self) -> Result<Const<'tcx>, ConstEvalErr<'tcx>> {
                         _ => span_bug!(span, "calling {:?} (of type {}) in constant",
                                        func, fn_ty)
                     };
+                    trace!("trans const fn call {:?}, {:?}, {:#?}", func, fn_ty, args);
 
                     let mut arg_vals = IndexVec::with_capacity(args.len());
                     for arg in args {
@@ -419,7 +490,7 @@ fn trans(&mut self) -> Result<Const<'tcx>, ConstEvalErr<'tcx>> {
                                 }
                                 _ => span_bug!(span, "{:?} in constant", terminator.kind)
                             }
-                        } else if let Some((op, is_checked)) = self.is_binop_lang_item(def_id) {
+                        } else if let Some((op, is_checked)) = tcx.is_binop_lang_item(def_id) {
                             (||{
                                 assert_eq!(arg_vals.len(), 2);
                                 let rhs = arg_vals.pop().unwrap()?;
@@ -470,37 +541,6 @@ fn trans(&mut self) -> Result<Const<'tcx>, ConstEvalErr<'tcx>> {
         }
     }
 
-    fn is_binop_lang_item(&mut self, def_id: DefId) -> Option<(mir::BinOp, bool)> {
-        let tcx = self.cx.tcx;
-        let items = tcx.lang_items();
-        let def_id = Some(def_id);
-        if items.i128_add_fn() == def_id { Some((mir::BinOp::Add, false)) }
-        else if items.u128_add_fn() == def_id { Some((mir::BinOp::Add, false)) }
-        else if items.i128_sub_fn() == def_id { Some((mir::BinOp::Sub, false)) }
-        else if items.u128_sub_fn() == def_id { Some((mir::BinOp::Sub, false)) }
-        else if items.i128_mul_fn() == def_id { Some((mir::BinOp::Mul, false)) }
-        else if items.u128_mul_fn() == def_id { Some((mir::BinOp::Mul, false)) }
-        else if items.i128_div_fn() == def_id { Some((mir::BinOp::Div, false)) }
-        else if items.u128_div_fn() == def_id { Some((mir::BinOp::Div, false)) }
-        else if items.i128_rem_fn() == def_id { Some((mir::BinOp::Rem, false)) }
-        else if items.u128_rem_fn() == def_id { Some((mir::BinOp::Rem, false)) }
-        else if items.i128_shl_fn() == def_id { Some((mir::BinOp::Shl, false)) }
-        else if items.u128_shl_fn() == def_id { Some((mir::BinOp::Shl, false)) }
-        else if items.i128_shr_fn() == def_id { Some((mir::BinOp::Shr, false)) }
-        else if items.u128_shr_fn() == def_id { Some((mir::BinOp::Shr, false)) }
-        else if items.i128_addo_fn() == def_id { Some((mir::BinOp::Add, true)) }
-        else if items.u128_addo_fn() == def_id { Some((mir::BinOp::Add, true)) }
-        else if items.i128_subo_fn() == def_id { Some((mir::BinOp::Sub, true)) }
-        else if items.u128_subo_fn() == def_id { Some((mir::BinOp::Sub, true)) }
-        else if items.i128_mulo_fn() == def_id { Some((mir::BinOp::Mul, true)) }
-        else if items.u128_mulo_fn() == def_id { Some((mir::BinOp::Mul, true)) }
-        else if items.i128_shlo_fn() == def_id { Some((mir::BinOp::Shl, true)) }
-        else if items.u128_shlo_fn() == def_id { Some((mir::BinOp::Shl, true)) }
-        else if items.i128_shro_fn() == def_id { Some((mir::BinOp::Shr, true)) }
-        else if items.u128_shro_fn() == def_id { Some((mir::BinOp::Shr, true)) }
-        else { None }
-    }
-
     fn store(&mut self,
              dest: &mir::Place<'tcx>,
              value: Result<Const<'tcx>, ConstEvalErr<'tcx>>,
index 34ac44cec025a3dd0af8ee2903affcedd5fe3b8f..b0cb7de824eb5e0ab6600f4ad8c35ba81d4bf3ab 100644 (file)
@@ -497,7 +497,7 @@ fn evaluate_array_len(&mut self,
         if let mir::Place::Local(index) = *place {
             if let LocalRef::Operand(Some(op)) = self.locals[index] {
                 if let ty::TyArray(_, n) = op.layout.ty.sty {
-                    let n = n.val.to_const_int().unwrap().to_u64().unwrap();
+                    let n = n.val.unwrap_u64();
                     return common::C_usize(bx.cx, n);
                 }
             }
index a261c12bcdd946dcc88cca1beeb2a5ce29f86d7c..eb02c05fd3957112882bd15f0e94a25c2a54f96d 100644 (file)
@@ -413,7 +413,7 @@ pub fn check_pat_walk(
                 let expected_ty = self.structurally_resolved_type(pat.span, expected);
                 let (inner_ty, slice_ty) = match expected_ty.sty {
                     ty::TyArray(inner_ty, size) => {
-                        let size = size.val.to_const_int().unwrap().to_u64().unwrap();
+                        let size = size.val.unwrap_u64();
                         let min_len = before.len() as u64 + after.len() as u64;
                         if slice.is_none() {
                             if min_len != size {
index 0f59973eab251245ddfc004b9b97e6a2d6e4c167..26b9649331025ddf10c795d662644795d4b6c875 100644 (file)
@@ -4029,9 +4029,7 @@ fn check_expr_kind(&self,
             };
 
             if let Ok(count) = count {
-                let zero_or_one = count.val.to_const_int().and_then(|count| {
-                    count.to_u64().map(|count| count <= 1)
-                }).unwrap_or(false);
+                let zero_or_one = count.val.to_u128().map_or(false, |count| count <= 1);
                 if !zero_or_one {
                     // For [foo, ..n] where n > 1, `foo` must have
                     // Copy type:
index 12791107ebb412234f4232964daba0664e2ce153..47a229cbd3b5b9f98b8bebc28cb2540f8874ef79 100644 (file)
@@ -447,10 +447,10 @@ fn lookup_op_method(&self, lhs_ty: Ty<'tcx>, other_tys: &[Ty<'tcx>], op: Op)
                 hir::BiBitOr => ("bitor", lang.bitor_trait()),
                 hir::BiShl => ("shl", lang.shl_trait()),
                 hir::BiShr => ("shr", lang.shr_trait()),
-                hir::BiLt => ("lt", lang.ord_trait()),
-                hir::BiLe => ("le", lang.ord_trait()),
-                hir::BiGe => ("ge", lang.ord_trait()),
-                hir::BiGt => ("gt", lang.ord_trait()),
+                hir::BiLt => ("lt", lang.partial_ord_trait()),
+                hir::BiLe => ("le", lang.partial_ord_trait()),
+                hir::BiGe => ("ge", lang.partial_ord_trait()),
+                hir::BiGt => ("gt", lang.partial_ord_trait()),
                 hir::BiEq => ("eq", lang.eq_trait()),
                 hir::BiNe => ("ne", lang.eq_trait()),
                 hir::BiAnd | hir::BiOr => {
index 1a7d8bb56780eb7cb7b444e7aa304bcec007648c..5ed35e8203cecacc03891325634a7cbd028b4aaa 100644 (file)
@@ -37,8 +37,8 @@
 use rustc::ty::{self, AdtKind, ToPolyTraitRef, Ty, TyCtxt};
 use rustc::ty::maps::Providers;
 use rustc::ty::util::IntTypeExt;
-use rustc::util::nodemap::FxHashSet;
-use util::nodemap::FxHashMap;
+use rustc::util::nodemap::{FxHashSet, FxHashMap};
+use rustc::mir::interpret::{Value, PrimVal};
 
 use rustc_const_math::ConstInt;
 
@@ -534,6 +534,18 @@ fn convert_enum_variant_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
             match result {
                 Ok(&ty::Const { val: ConstVal::Integral(x), .. }) => Some(x),
+                Ok(&ty::Const {
+                    val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(b))),
+                    ..
+                }) => {
+                    use syntax::attr::IntType;
+                    Some(match repr_type {
+                        IntType::SignedInt(int_type) => ConstInt::new_signed(
+                            b as i128, int_type, tcx.sess.target.isize_ty).unwrap(),
+                        IntType::UnsignedInt(uint_type) => ConstInt::new_unsigned(
+                            b, uint_type, tcx.sess.target.usize_ty).unwrap(),
+                    })
+                }
                 _ => None
             }
         } else if let Some(discr) = repr_type.disr_incr(tcx, prev_discr) {
index d9bd96b0d769fea0fb7ae6c686eb57f17b5470ef..40385cabf5661ba32e3f7055babd4487819f5d38 100644 (file)
@@ -86,6 +86,7 @@
 #![feature(refcell_replace_swap)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(slice_patterns)]
+#![feature(i128_type)]
 
 #[macro_use] extern crate log;
 #[macro_use] extern crate syntax;
index d6084d5a6da9237878cddb9d955f7d86736fbad7..3fb5621c8ae3ba4429d9584b0046feb9507d8f3d 100644 (file)
@@ -49,7 +49,7 @@ fn main() {
 //         _3 = &'23_1rs _2;
 //         StorageLive(_5);
 //         _5 = _2;
-//         switchInt(move _5) -> [0u8: bb5, otherwise: bb4];
+//         switchInt(move _5) -> [false: bb5, otherwise: bb4];
 //     }
 //     bb3: {
 //         ...
index 46548f1cce97868213d29f08a931a696dc33289a..070bde8e3c3e6f7faa15551307266e0f5afeb6c5 100644 (file)
@@ -51,7 +51,7 @@ fn main() {
 //         _3 = &'26_1rs _1;
 //         StorageLive(_5);
 //         _5 = _1;
-//         switchInt(move _5) -> [0u8: bb5, otherwise: bb4];
+//         switchInt(move _5) -> [false: bb5, otherwise: bb4];
 //     }
 //     bb3: {
 //         ...
index 0f1d714cc6fd2ec68758f34ed0edba7da810d13f..6d9a27eeeb4560dc276027cd92a4e7cd36bc4f50 100644 (file)
@@ -72,7 +72,7 @@ fn main() {
 //    bb4: {
 //        StorageLive(_7);
 //        _7 = _1;
-//        switchInt(move _7) -> [0u8: bb6, otherwise: bb5];
+//        switchInt(move _7) -> [false: bb6, otherwise: bb5];
 //    }
 //    bb5: {
 //        _0 = ();
index 2a82e2675b67dafe59c8e1dfb0f28631826f85dd..83425a72f4598e38131070b9cbaa9d9d6766df4c 100644 (file)
@@ -103,7 +103,7 @@ fn query() -> bool { true }
 //         _11 = const query() -> [return: bb6, unwind: bb3];
 //     }
 //     bb6: {
-//         switchInt(move _11) -> [0u8: bb8, otherwise: bb7];
+//         switchInt(move _11) -> [false: bb8, otherwise: bb7];
 //     }
 //     bb7: {
 //         _0 = ();
index 3151c0643079c175bc4c4744760bb201cdc63f27..a9eea26f46643843d2270ea4402b78467a49d0e2 100644 (file)
@@ -36,7 +36,7 @@ fn main() {
 //     bb3: {
 //         StorageLive(_4);
 //         _4 = _1;
-//         switchInt(move _4) -> [0u8: bb5, otherwise: bb4];
+//         switchInt(move _4) -> [false: bb5, otherwise: bb4];
 //     }
 //     bb4: {
 //         _0 = ();
index ba1b54d59f69a4a0860b05c193c59ecfc2d238aa..596bb4e115dfcd65682db12d3a3cf5cef6ea34a7 100644 (file)
@@ -93,7 +93,7 @@ fn main() {
 //      _7 = const guard() -> [return: bb10, unwind: bb1];
 //  }
 //  bb10: { // end of guard
-//      switchInt(move _7) -> [0u8: bb11, otherwise: bb2];
+//      switchInt(move _7) -> [false: bb11, otherwise: bb2];
 //  }
 //  bb11: { // to pre_binding2
 //      falseEdges -> [real: bb5, imaginary: bb5];
@@ -157,7 +157,7 @@ fn main() {
 //      _7 = const guard() -> [return: bb10, unwind: bb1];
 //  }
 //  bb10: { // end of guard
-//      switchInt(move _7) -> [0u8: bb11, otherwise: bb2];
+//      switchInt(move _7) -> [false: bb11, otherwise: bb2];
 //  }
 //  bb11: { // to pre_binding2
 //      falseEdges -> [real: bb6, imaginary: bb5];
@@ -219,7 +219,7 @@ fn main() {
 //     _9 = const guard() -> [return: bb10, unwind: bb1];
 // }
 // bb10: { //end of guard
-//    switchInt(move _9) -> [0u8: bb11, otherwise: bb2];
+//    switchInt(move _9) -> [false: bb11, otherwise: bb2];
 // }
 // bb11: { // to pre_binding2
 //     falseEdges -> [real: bb5, imaginary: bb5];
@@ -239,8 +239,8 @@ fn main() {
 //     _11 = const guard2(move _12) -> [return: bb14, unwind: bb1];
 // }
 // bb14: { // end of guard2
-//     StorageDead(_12);
-//     switchInt(move _11) -> [0u8: bb15, otherwise: bb3];
+//     StorageDead(_11);
+//     switchInt(move _11) -> [false: bb15, otherwise: bb3];
 // }
 // bb15: { // to pre_binding4
 //     falseEdges -> [real: bb7, imaginary: bb7];
index e9834305550c39088b170e16695c9ab56b17188d..19d733d4f6b6a8931bdc0a4d2b5617b970b7b85c 100644 (file)
@@ -41,7 +41,7 @@ fn main() {
 //            | Live variables on entry to bb2[0]: [_1, _3]
 //        _2 = &'_#2r _1[_3];
 //            | Live variables on entry to bb2[1]: [_2]
-//        switchInt(const true) -> [0u8: bb4, otherwise: bb3];
+//        switchInt(const true) -> [false: bb4, otherwise: bb3];
 //    }
 // END rustc.main.nll.0.mir
 // START rustc.main.nll.0.mir
index 35786643648eb12d48d8367491ccb35d2adc3ef0..52d5892e6560b96ca2165147535566a8c3711375 100644 (file)
@@ -17,7 +17,7 @@ fn main() {
 // END RUST SOURCE
 // START rustc.main.SimplifyBranches-initial.before.mir
 // bb0: {
-//     switchInt(const false) -> [0u8: bb3, otherwise: bb2];
+//     switchInt(const false) -> [false: bb3, otherwise: bb2];
 // }
 // END rustc.main.SimplifyBranches-initial.before.mir
 // START rustc.main.SimplifyBranches-initial.after.mir
index 6b7f631ff4c8d2e3cdd354f28baf011af34e54c5..885edb55ed86c9a95ba09cdd68c1eaea1a62463d 100644 (file)
@@ -19,8 +19,7 @@
 
 const NEG_128: i8 = -128;
 const NEG_NEG_128: i8 = -NEG_128;
-//~^ ERROR constant evaluation error
-//~| attempt to negate with overflow
+//~^ ERROR E0080
 
 fn main() {
     match -128i8 {
index 4423fdec33a85d800a9b248a4004f5ac20d0ec76..a1b90f623cdae1d5b9c35bee0c156ec52704f82d 100644 (file)
@@ -21,8 +21,7 @@
 
 const A_I8_T
     : [u32; (i8::MAX as i8 + 1i8) as usize]
-    //~^ ERROR constant evaluation error
-    //~| WARNING constant evaluation error
+    //~^ ERROR E0080
     = [0; (i8::MAX as usize) + 1];
 
 fn main() {
index 85ab2a00521645ded9cc456184b2bfbc30cc4def..86c5e873df866d72b69be554b4cf5fa08233e4cb 100644 (file)
@@ -16,8 +16,6 @@ const fn foo(x: u32) -> u32 {
 
 fn main() {
     const X: u32 = 0-1; //~ ERROR constant evaluation error
-    //~^ WARN constant evaluation error
     const Y: u32 = foo(0-1); //~ ERROR constant evaluation error
-    //~^ WARN constant evaluation error
     println!("{} {}", X, Y);
 }
index 24d4457f01d70439637a2bf74e08a7e61cfabd15..bfd6a4090649b7cfd8bfcef032efe092bdd0939b 100644 (file)
@@ -9,10 +9,11 @@
 // except according to those terms.
 
 // Encountered while testing #44614.
+// must-compile-successfully
 
 pub fn main() {
     // Constant of generic type (int)
-    const X: &'static u32 = &22; //~ ERROR constant evaluation error
+    const X: &'static u32 = &22;
     assert_eq!(0, match &22 {
         X => 0,
         _ => 1,
index ac1c2fe5432dedf6b6bac401447761afc8aac1aa..dc1526a7079d44e75175e74d19b7ae47247a70cf 100644 (file)
 const X : usize = 2;
 
 const fn f(x: usize) -> usize {
-    let mut sum = 0; //~ ERROR blocks in constant functions are limited
-    for i in 0..x { //~ ERROR calls in constant functions
-    //~| ERROR constant function contains unimplemented
+    let mut sum = 0;
+    //~^ ERROR E0016
+    for i in 0..x {
+        //~^ ERROR E0015
+        //~| ERROR E0019
         sum += i;
     }
-    sum //~ ERROR E0080
-        //~| non-constant path in constant
+    sum
 }
 
 #[allow(unused_variables)]
 fn main() {
     let a : [i32; f(X)];
-    //~^ WARNING constant evaluation error: non-constant path
+    //~^ ERROR E0080
 }
index e738a5e4ff308f72a90b6b9317d5a3aded0161bf..26c238992ab60d1b93d5dd47f3ece68b88f91807 100644 (file)
@@ -1,3 +1,4 @@
+<<<<<<< HEAD
 warning: constant evaluation error: non-constant path in constant expression
   --> $DIR/const-fn-error.rs:27:19
    |
@@ -10,6 +11,12 @@ error[E0016]: blocks in constant functions are limited to items and tail express
   --> $DIR/const-fn-error.rs:16:19
    |
 LL |     let mut sum = 0; //~ ERROR blocks in constant functions are limited
+=======
+error[E0016]: blocks in constant functions are limited to items and tail expressions
+  --> $DIR/const-fn-error.rs:16:19
+   |
+16 |     let mut sum = 0;
+>>>>>>> Produce  instead of pointers
    |                   ^
 
 error[E0015]: calls in constant functions are limited to constant functions, struct and enum constructors
@@ -25,6 +32,7 @@ LL |     for i in 0..x { //~ ERROR calls in constant functions
    |              ^^^^
 
 error[E0080]: constant evaluation error
+<<<<<<< HEAD
   --> $DIR/const-fn-error.rs:21:5
    |
 LL |     sum //~ ERROR E0080
@@ -35,6 +43,12 @@ note: for constant expression here
    |
 LL |     let a : [i32; f(X)];
    |             ^^^^^^^^^^^
+=======
+  --> $DIR/const-fn-error.rs:28:19
+   |
+28 |     let a : [i32; f(X)];
+   |                   ^^^^ miri failed: machine error: Cannot evaluate within constants: "calling non-const fn `<I as std::iter::IntoIterator><std::ops::Range<usize>>::into_iter`"
+>>>>>>> Produce  instead of pointers
 
 error: aborting due to 4 previous errors
 
index 823cc988947cb0aeead65453a554c134dfbf5913..7582d0efa812e1d0082a0247b2d7789f3edc67eb 100644 (file)
@@ -15,9 +15,8 @@
 const ONE: usize = 1;
 const TWO: usize = 2;
 const LEN: usize = ONE - TWO;
-//~^ ERROR constant evaluation error [E0080]
-//~| WARN attempt to subtract with overflow
 
 fn main() {
     let a: [i8; LEN] = unimplemented!();
+//~^ ERROR E0080
 }
index 263c0bdc64c6f40208930ef2a0a3c5b02235efc8..09b24d1ffa208ba8d16fa47fea13523f6ccbaccd 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// must-compile-successfully
+
 #![feature(const_fn)]
 
 #[derive(PartialEq, Eq)]
@@ -20,8 +22,6 @@ enum Cake {
 struct Pair<A, B>(A, B);
 
 const BOO: Pair<Cake, Cake> = Pair(Marmor, BlackForest);
-//~^ ERROR: constant evaluation error [E0080]
-//~| unimplemented constant expression: tuple struct constructors
 const FOO: Cake = BOO.1;
 
 const fn foo() -> Cake {
index 0d61878cd8073b25164202a1c41aa42803df15e5..eb5f746774cf13886c8eb9ffa377b8010ad9548e 100644 (file)
@@ -8,10 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// must-compile-successfully
 
 fn main() {
     const ARR: [i32; 6] = [42, 43, 44, 45, 46, 47];
     const IDX: usize = 3;
     const VAL: i32 = ARR[IDX];
-    const BLUB: [i32; (ARR[0] - 41) as usize] = [5]; //~ ERROR constant evaluation error
+    const BLUB: [i32; (ARR[0] - 41) as usize] = [5];
 }
index 42e3c05a38c7e459ed58b3f5e9574ec8a31cc556..24cd20a84a9feebd3997a671788a8e90f568a9a0 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // aux-build:issue_38875_b.rs
+// must-compile-successfully
 
 extern crate issue_38875_b;
 
index a4c969ba20c4674d677f1d59f39c9440cfe05237..aeafb45e6a552658f7e0b3968d0eaafe109cb927 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// must-compile-successfully
+
 union U {
     a: usize,
     b: usize,
@@ -16,9 +18,6 @@ union U {
 const C: U = U { a: 10 };
 
 fn main() {
-    unsafe {
-        let a: [u8; C.a]; // OK
-        let b: [u8; C.b]; //~ ERROR constant evaluation error
-                          //~| WARNING constant evaluation error
-    }
+    let a: [u8; unsafe { C.a }];
+    let b: [u8; unsafe { C.b }];
 }