]> git.lizzy.rs Git - rust.git/commitdiff
Nuke the entire ctfe from orbit, it's the only way to be sure
authorOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>
Tue, 16 Jan 2018 08:28:27 +0000 (09:28 +0100)
committerOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>
Thu, 8 Mar 2018 07:08:14 +0000 (08:08 +0100)
53 files changed:
src/librustc/ich/impls_ty.rs
src/librustc/lint/builtin.rs
src/librustc/middle/const_val.rs
src/librustc/mir/mod.rs
src/librustc/ty/context.rs
src/librustc/ty/error.rs
src/librustc/ty/flags.rs
src/librustc/ty/mod.rs
src/librustc/ty/relate.rs
src/librustc/ty/structural_impls.rs
src/librustc/ty/util.rs
src/librustc/ty/walk.rs
src/librustc/ty/wf.rs
src/librustc/util/ppaux.rs
src/librustc_driver/driver.rs
src/librustc_lint/builtin.rs
src/librustc_lint/lib.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/test.rs
src/librustc_mir/build/misc.rs
src/librustc_mir/const_eval/_match.rs
src/librustc_mir/const_eval/check.rs [new file with mode: 0644]
src/librustc_mir/const_eval/eval.rs
src/librustc_mir/const_eval/mod.rs
src/librustc_mir/const_eval/pattern.rs
src/librustc_mir/diagnostics.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/place.rs
src/librustc_mir/shim.rs
src/librustc_mir/transform/elaborate_drops.rs
src/librustc_mir/transform/generator.rs
src/librustc_mir/transform/simplify_branches.rs
src/librustc_mir/util/elaborate_drops.rs
src/librustc_passes/consts.rs
src/librustc_passes/diagnostics.rs
src/librustc_trans/mir/analyze.rs
src/librustc_trans/mir/constant.rs
src/librustc_typeck/collect.rs
src/test/compile-fail/issue-31109.rs
src/test/compile-fail/issue-39559-2.rs
src/test/compile-fail/issue-41255.rs
src/test/compile-fail/lint-exceeding-bitshifts.rs
src/test/compile-fail/lint-type-overflow2.rs
src/test/compile-fail/rfc1445/match-forbidden-without-eq.rs
src/test/compile-fail/thread-local-in-ctfe.rs

index 4d802491c96edf8eeba9f5ba2873cba698b75ccb..08a42e61ea0001bf508dd41fe3445aae6ef9a33b 100644 (file)
@@ -338,53 +338,10 @@ fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         use middle::const_val::ConstVal::*;
-        use middle::const_val::ConstAggregate::*;
 
         mem::discriminant(self).hash_stable(hcx, hasher);
 
         match *self {
-            Integral(ref value) => {
-                value.hash_stable(hcx, hasher);
-            }
-            Float(ref value) => {
-                value.hash_stable(hcx, hasher);
-            }
-            Str(ref value) => {
-                value.hash_stable(hcx, hasher);
-            }
-            ByteStr(ref value) => {
-                value.hash_stable(hcx, hasher);
-            }
-            Bool(value) => {
-                value.hash_stable(hcx, hasher);
-            }
-            Char(value) => {
-                value.hash_stable(hcx, hasher);
-            }
-            Variant(def_id) => {
-                def_id.hash_stable(hcx, hasher);
-            }
-            Function(def_id, substs) => {
-                def_id.hash_stable(hcx, hasher);
-                hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
-                    substs.hash_stable(hcx, hasher);
-                });
-            }
-            Aggregate(Struct(ref name_values)) => {
-                let mut values = name_values.to_vec();
-                values.sort_unstable_by_key(|&(ref name, _)| name.clone());
-                values.hash_stable(hcx, hasher);
-            }
-            Aggregate(Tuple(ref value)) => {
-                value.hash_stable(hcx, hasher);
-            }
-            Aggregate(Array(ref value)) => {
-                value.hash_stable(hcx, hasher);
-            }
-            Aggregate(Repeat(ref value, times)) => {
-                value.hash_stable(hcx, hasher);
-                times.hash_stable(hcx, hasher);
-            }
             Unevaluated(def_id, substs) => {
                 def_id.hash_stable(hcx, hasher);
                 substs.hash_stable(hcx, hasher);
index b68b7dc6c067256d1fea467c43f8749517006ce2..a951265d458bf2e6a78ec67dad8e234593227b94 100644 (file)
 use session::config::Epoch;
 use syntax::codemap::Span;
 
+declare_lint! {
+    pub EXCEEDING_BITSHIFTS,
+    Deny,
+    "shift exceeds the type's number of bits"
+}
+
 declare_lint! {
     pub CONST_ERR,
     Warn,
     Epoch::Epoch2018
 }
 
+declare_lint! {
+    pub ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
+    Warn,
+    "floating-point literals cannot be used in patterns"
+}
+
 /// Does nothing as a lint pass, but registers some `Lint`s
 /// which are used by other parts of the compiler.
 #[derive(Copy, Clone)]
 impl LintPass for HardwiredLints {
     fn get_lints(&self) -> LintArray {
         lint_array!(
+            ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
+            EXCEEDING_BITSHIFTS,
             UNUSED_IMPORTS,
             UNUSED_EXTERN_CRATES,
             UNUSED_QUALIFICATIONS,
index cf322010e05c3a57904c6a635cc0899cbd977d0c..dd99305809c2840b6c0a3470258aa7b8dc466801 100644 (file)
@@ -18,9 +18,7 @@
 
 use graphviz::IntoCow;
 use errors::DiagnosticBuilder;
-use serialize::{self, Encodable, Encoder, Decodable, Decoder};
-use syntax::symbol::InternedString;
-use syntax::ast;
+use serialize;
 use syntax_pos::Span;
 
 use std::borrow::Cow;
 
 #[derive(Copy, Clone, Debug, Hash, RustcEncodable, RustcDecodable, Eq, PartialEq)]
 pub enum ConstVal<'tcx> {
-    Integral(ConstInt),
-    Float(ConstFloat),
-    Str(InternedString),
-    ByteStr(ByteArray<'tcx>),
-    Bool(bool),
-    Char(char),
-    Variant(DefId),
-    Function(DefId, &'tcx Substs<'tcx>),
-    Aggregate(ConstAggregate<'tcx>),
     Unevaluated(DefId, &'tcx Substs<'tcx>),
-    /// A miri value, currently only produced if --miri is enabled
     Value(Value),
 }
 
@@ -50,32 +38,9 @@ pub struct ByteArray<'tcx> {
 
 impl<'tcx> serialize::UseSpecializedDecodable for ByteArray<'tcx> {}
 
-#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
-pub enum ConstAggregate<'tcx> {
-    Struct(&'tcx [(ast::Name, &'tcx ty::Const<'tcx>)]),
-    Tuple(&'tcx [&'tcx ty::Const<'tcx>]),
-    Array(&'tcx [&'tcx ty::Const<'tcx>]),
-    Repeat(&'tcx ty::Const<'tcx>, u64),
-}
-
-impl<'tcx> Encodable for ConstAggregate<'tcx> {
-    fn encode<S: Encoder>(&self, _: &mut S) -> Result<(), S::Error> {
-        bug!("should never encode ConstAggregate::{:?}", self)
-    }
-}
-
-impl<'tcx> Decodable for ConstAggregate<'tcx> {
-    fn decode<D: Decoder>(_: &mut D) -> Result<Self, D::Error> {
-        bug!("should never decode ConstAggregate")
-    }
-}
-
 impl<'tcx> ConstVal<'tcx> {
     pub fn to_u128(&self) -> Option<u128> {
         match *self {
-            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)
             },
@@ -93,7 +58,6 @@ pub fn unwrap_u64(&self) -> u64 {
     }
     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) {
index d35cbd0027fb68e41d52da076a82ce1a59bfc93f..d8994351418199910f06cb5ac6255324c476c3f4 100644 (file)
@@ -33,7 +33,6 @@
 use util::ppaux;
 use std::slice;
 use hir::{self, InlineAsm};
-use std::ascii;
 use std::borrow::{Cow};
 use std::cell::Ref;
 use std::fmt::{self, Debug, Formatter, Write};
@@ -1539,12 +1538,8 @@ pub fn function_handle<'a>(
             ty,
             literal: Literal::Value {
                 value: tcx.mk_const(ty::Const {
-                    val: if tcx.sess.opts.debugging_opts.miri {
-                        // ZST function type
-                        ConstVal::Value(Value::ByVal(PrimVal::Undef))
-                    } else {
-                        ConstVal::Function(def_id, substs)
-                    },
+                    // ZST function type
+                    val: ConstVal::Value(Value::ByVal(PrimVal::Undef)),
                     ty
                 })
             },
@@ -1877,21 +1872,6 @@ fn fmt(&self, fmt: &mut Formatter) -> 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.val {
-        Float(f) => write!(fmt, "{:?}", f),
-        Integral(n) => write!(fmt, "{}", n),
-        Str(s) => write!(fmt, "{:?}", s),
-        ByteStr(bytes) => {
-            let escaped: String = bytes.data
-                .iter()
-                .flat_map(|&ch| ascii::escape_default(ch).map(|c| c as char))
-                .collect();
-            write!(fmt, "b\"{}\"", escaped)
-        }
-        Bool(b) => write!(fmt, "{:?}", b),
-        Char(c) => write!(fmt, "{:?}", c),
-        Variant(def_id) |
-        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) => print_miri_value(val, const_val.ty, fmt),
     }
@@ -1918,7 +1898,7 @@ fn print_miri_value<W: Write>(value: Value, ty: Ty, f: &mut W) -> fmt::Result {
                 let alloc = tcx
                     .interpret_interner
                     .borrow()
-                    .get_alloc(ptr.alloc_id.0)
+                    .get_alloc(ptr.alloc_id)
                     .expect("miri alloc not found");
                 assert_eq!(len as usize as u128, len);
                 let slice = &alloc.bytes[(ptr.offset as usize)..][..(len as usize)];
index 17926eeec0020033254faa17729649c322de0845..ebd78467c3b9ea63051566c6e4e124576c0d90aa 100644 (file)
@@ -54,7 +54,7 @@
                                            StableHasher, StableHasherResult,
                                            StableVec};
 use arena::{TypedArena, DroplessArena};
-use rustc_const_math::{ConstInt, ConstUsize};
+use rustc_const_math::ConstUsize;
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_data_structures::sync::Lrc;
 use std::any::Any;
@@ -909,7 +909,7 @@ pub struct InterpretInterner<'tcx> {
     /// Reverse map of `alloc_cache`
     ///
     /// Multiple globals may share the same memory
-    global_cache: FxHashMap<interpret::Pointer, Vec<interpret::GlobalId<'tcx>>>,
+    global_cache: FxHashMap<interpret::AllocId, Vec<interpret::GlobalId<'tcx>>>,
 
     /// The AllocId to assign to the next new regular allocation.
     /// Always incremented, never gets smaller.
@@ -959,20 +959,17 @@ pub fn get_cached(
     pub fn cache(
         &mut self,
         global_id: interpret::GlobalId<'tcx>,
-        ptr: interpret::AllocId,
+        alloc_id: interpret::AllocId,
     ) {
-        if let interpret::PrimVal::Ptr(ptr) = ptr.primval {
-            assert!(ptr.offset == 0);
-        }
-        self.global_cache.entry(ptr).or_default().push(global_id);
-        if let Some(old) = self.alloc_cache.insert(global_id, ptr) {
+        self.global_cache.entry(alloc_id).or_default().push(global_id);
+        if let Some(old) = self.alloc_cache.insert(global_id, alloc_id) {
             bug!("tried to cache {:?}, but was already existing as {:#?}", global_id, old);
         }
     }
 
     pub fn get_globals(
         &self,
-        ptr: interpret::Pointer,
+        ptr: interpret::AllocId,
     ) -> &[interpret::GlobalId<'tcx>] {
         match self.global_cache.get(&ptr) {
             Some(v) => v,
@@ -2099,11 +2096,7 @@ 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: if self.sess.opts.debugging_opts.miri {
-                ConstVal::Value(Value::ByVal(PrimVal::Bytes(n.as_u64().into())))
-            } else {
-                ConstVal::Integral(ConstInt::Usize(n))
-            },
+            val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(n.as_u64().into()))),
             ty: self.types.usize
         })))
     }
index 07920c58271cd63dc135762dfcb731271a44c5a2..5dc78d84da8355e679fc2432d2a07f7867e4536f 100644 (file)
@@ -19,8 +19,6 @@
 use errors::DiagnosticBuilder;
 use syntax_pos::Span;
 
-use rustc_const_math::ConstInt;
-
 use hir;
 
 #[derive(Clone, Copy, Debug)]
@@ -188,8 +186,6 @@ pub fn sort_string(&self, tcx: TyCtxt<'a, 'gcx, 'lcx>) -> String {
             ty::TyForeign(def_id) => format!("extern type `{}`", tcx.item_path_str(def_id)),
             ty::TyArray(_, n) => {
                 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(),
index 60bf4afc2fc887ab5aca5edfeeb2c02161f6437f..f067789771c59ba6115e782dde94e85dbcc136e1 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use middle::const_val::{ConstVal, ConstAggregate};
+use middle::const_val::ConstVal;
 use ty::subst::Substs;
 use ty::{self, Ty, TypeFlags, TypeFoldable};
 
@@ -218,31 +218,7 @@ fn add_region(&mut self, r: ty::Region) {
     fn add_const(&mut self, constant: &ty::Const) {
         self.add_ty(constant.ty);
         match constant.val {
-            ConstVal::Integral(_) |
-            ConstVal::Float(_) |
-            ConstVal::Str(_) |
-            ConstVal::ByteStr(_) |
-            ConstVal::Bool(_) |
-            ConstVal::Char(_) |
-            ConstVal::Value(_) |
-            ConstVal::Variant(_) => {}
-            ConstVal::Function(_, substs) => {
-                self.add_substs(substs);
-            }
-            ConstVal::Aggregate(ConstAggregate::Struct(fields)) => {
-                for &(_, v) in fields {
-                    self.add_const(v);
-                }
-            }
-            ConstVal::Aggregate(ConstAggregate::Tuple(fields)) |
-            ConstVal::Aggregate(ConstAggregate::Array(fields)) => {
-                for v in fields {
-                    self.add_const(v);
-                }
-            }
-            ConstVal::Aggregate(ConstAggregate::Repeat(v, _)) => {
-                self.add_const(v);
-            }
+            ConstVal::Value(_) => {}
             ConstVal::Unevaluated(_, substs) => {
                 self.add_flags(TypeFlags::HAS_PROJECTION);
                 self.add_substs(substs);
index 1577e78d81e22e273e4da5c102f9d722cca4077e..8c955bf340e8d2f449db4c3d72a5c61d8508e760 100644 (file)
@@ -1836,9 +1836,6 @@ pub fn discriminants(&'a self, tcx: TyCtxt<'a, 'gcx, 'tcx>)
             if let VariantDiscr::Explicit(expr_did) = v.discr {
                 let substs = Substs::identity_for_item(tcx.global_tcx(), expr_did);
                 match tcx.const_eval(param_env.and((expr_did, substs))) {
-                    Ok(&ty::Const { val: ConstVal::Integral(v), .. }) => {
-                        discr = v;
-                    }
                     Ok(&ty::Const {
                         val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(b))),
                         ..
@@ -1889,10 +1886,6 @@ pub fn discriminant_for_variant(&self,
                 ty::VariantDiscr::Explicit(expr_did) => {
                     let substs = Substs::identity_for_item(tcx.global_tcx(), expr_did);
                     match tcx.const_eval(param_env.and((expr_did, substs))) {
-                        Ok(&ty::Const { val: ConstVal::Integral(v), .. }) => {
-                            explicit_value = v;
-                            break;
-                        }
                         Ok(&ty::Const {
                             val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(b))),
                             ..
index bac78508993a5c1dca48b8d8c8b99df9d19dbe51..2cbe9da88b51b392123f898798573ee4d1802b00 100644 (file)
@@ -483,7 +483,6 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
             assert_eq!(sz_b.ty, tcx.types.usize);
             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.
@@ -491,9 +490,6 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
                         match tcx.lift_to_global(&substs) {
                             Some(substs) => {
                                 match tcx.const_eval(param_env.and((def_id, substs))) {
-                                    Ok(&ty::Const { val: ConstVal::Integral(x), .. }) => {
-                                        return Ok(x.to_u64().unwrap());
-                                    }
                                     Ok(&ty::Const {
                                         val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(b))),
                                         ..
index 80250949b0b4af64985ed8652b4bc8f3f0d94e3e..ad66cbd9eab3bd777334bd4e02b5d3a7afd27499 100644 (file)
@@ -13,7 +13,7 @@
 //! hand, though we've recently added some macros (e.g.,
 //! `BraceStructLiftImpl!`) to help with the tedium.
 
-use middle::const_val::{self, ConstVal, ConstAggregate, ConstEvalErr};
+use middle::const_val::{self, ConstVal, ConstEvalErr};
 use ty::{self, Lift, Ty, TyCtxt};
 use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
 use rustc_data_structures::accumulate_vec::AccumulateVec;
@@ -1410,54 +1410,7 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
 impl<'tcx> TypeFoldable<'tcx> for ConstVal<'tcx> {
     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
         match *self {
-            ConstVal::Integral(i) => ConstVal::Integral(i),
-            ConstVal::Float(f) => ConstVal::Float(f),
-            ConstVal::Str(s) => ConstVal::Str(s),
-            ConstVal::ByteStr(b) => ConstVal::ByteStr(b),
-            ConstVal::Bool(b) => ConstVal::Bool(b),
-            ConstVal::Char(c) => ConstVal::Char(c),
             ConstVal::Value(v) => ConstVal::Value(v),
-            ConstVal::Variant(def_id) => ConstVal::Variant(def_id),
-            ConstVal::Function(def_id, substs) => {
-                ConstVal::Function(def_id, substs.fold_with(folder))
-            }
-            ConstVal::Aggregate(ConstAggregate::Struct(fields)) => {
-                let new_fields: Vec<_> = fields.iter().map(|&(name, v)| {
-                    (name, v.fold_with(folder))
-                }).collect();
-                let fields = if new_fields == fields {
-                    fields
-                } else {
-                    folder.tcx().alloc_name_const_slice(&new_fields)
-                };
-                ConstVal::Aggregate(ConstAggregate::Struct(fields))
-            }
-            ConstVal::Aggregate(ConstAggregate::Tuple(fields)) => {
-                let new_fields: Vec<_> = fields.iter().map(|v| {
-                    v.fold_with(folder)
-                }).collect();
-                let fields = if new_fields == fields {
-                    fields
-                } else {
-                    folder.tcx().alloc_const_slice(&new_fields)
-                };
-                ConstVal::Aggregate(ConstAggregate::Tuple(fields))
-            }
-            ConstVal::Aggregate(ConstAggregate::Array(fields)) => {
-                let new_fields: Vec<_> = fields.iter().map(|v| {
-                    v.fold_with(folder)
-                }).collect();
-                let fields = if new_fields == fields {
-                    fields
-                } else {
-                    folder.tcx().alloc_const_slice(&new_fields)
-                };
-                ConstVal::Aggregate(ConstAggregate::Array(fields))
-            }
-            ConstVal::Aggregate(ConstAggregate::Repeat(v, count)) => {
-                let v = v.fold_with(folder);
-                ConstVal::Aggregate(ConstAggregate::Repeat(v, count))
-            }
             ConstVal::Unevaluated(def_id, substs) => {
                 ConstVal::Unevaluated(def_id, substs.fold_with(folder))
             }
@@ -1466,25 +1419,7 @@ fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F)
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
         match *self {
-            ConstVal::Integral(_) |
-            ConstVal::Float(_) |
-            ConstVal::Str(_) |
-            ConstVal::ByteStr(_) |
-            ConstVal::Bool(_) |
-            ConstVal::Char(_) |
-            ConstVal::Value(_) |
-            ConstVal::Variant(_) => false,
-            ConstVal::Function(_, substs) => substs.visit_with(visitor),
-            ConstVal::Aggregate(ConstAggregate::Struct(fields)) => {
-                fields.iter().any(|&(_, v)| v.visit_with(visitor))
-            }
-            ConstVal::Aggregate(ConstAggregate::Tuple(fields)) |
-            ConstVal::Aggregate(ConstAggregate::Array(fields)) => {
-                fields.iter().any(|v| v.visit_with(visitor))
-            }
-            ConstVal::Aggregate(ConstAggregate::Repeat(v, _)) => {
-                v.visit_with(visitor)
-            }
+            ConstVal::Value(_) => false,
             ConstVal::Unevaluated(_, substs) => substs.visit_with(visitor),
         }
     }
index 6ad2901ce3a100210e13ae67c0b96192dd0d5830..6ae0d520e54d36795fb418aa46d423f2006dc833 100644 (file)
@@ -765,7 +765,6 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
             TyArray(_, n) => {
                 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 4ef7706c45e3e443196b47d43e0f48dcb5f8f3e7..722fdfe773a98bac45eab8bbf6a4ad5a260337ba 100644 (file)
@@ -11,7 +11,7 @@
 //! An iterator over the type substructure.
 //! WARNING: this does not keep track of the region depth.
 
-use middle::const_val::{ConstVal, ConstAggregate};
+use middle::const_val::ConstVal;
 use ty::{self, Ty};
 use rustc_data_structures::small_vec::SmallVec;
 use rustc_data_structures::accumulate_vec::IntoIter as AccIntoIter;
@@ -140,31 +140,7 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) {
 
 fn push_const<'tcx>(stack: &mut TypeWalkerStack<'tcx>, constant: &'tcx ty::Const<'tcx>) {
     match constant.val {
-        ConstVal::Integral(_) |
-        ConstVal::Float(_) |
-        ConstVal::Str(_) |
-        ConstVal::ByteStr(_) |
-        ConstVal::Bool(_) |
-        ConstVal::Char(_) |
-        ConstVal::Value(_) |
-        ConstVal::Variant(_) => {}
-        ConstVal::Function(_, substs) => {
-            stack.extend(substs.types().rev());
-        }
-        ConstVal::Aggregate(ConstAggregate::Struct(fields)) => {
-            for &(_, v) in fields.iter().rev() {
-                push_const(stack, v);
-            }
-        }
-        ConstVal::Aggregate(ConstAggregate::Tuple(fields)) |
-        ConstVal::Aggregate(ConstAggregate::Array(fields)) => {
-            for v in fields.iter().rev() {
-                push_const(stack, v);
-            }
-        }
-        ConstVal::Aggregate(ConstAggregate::Repeat(v, _)) => {
-            push_const(stack, v);
-        }
+        ConstVal::Value(_) => {}
         ConstVal::Unevaluated(_, substs) => {
             stack.extend(substs.types().rev());
         }
index 443e0e857a7a1dab7cfd9569b34ddb193bd33daa..49ae79ae9c92c69b9babf214f6168d3d8da97bc6 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use hir::def_id::DefId;
-use middle::const_val::{ConstVal, ConstAggregate};
+use middle::const_val::ConstVal;
 use infer::InferCtxt;
 use ty::subst::Substs;
 use traits;
@@ -217,29 +217,7 @@ fn compute_projection(&mut self, data: ty::ProjectionTy<'tcx>) {
     fn compute_const(&mut self, constant: &'tcx ty::Const<'tcx>) {
         self.require_sized(constant.ty, traits::ConstSized);
         match constant.val {
-            ConstVal::Integral(_) |
-            ConstVal::Float(_) |
-            ConstVal::Str(_) |
-            ConstVal::ByteStr(_) |
-            ConstVal::Bool(_) |
-            ConstVal::Char(_) |
-            ConstVal::Variant(_) |
-            ConstVal::Value(_) |
-            ConstVal::Function(..) => {}
-            ConstVal::Aggregate(ConstAggregate::Struct(fields)) => {
-                for &(_, v) in fields {
-                    self.compute_const(v);
-                }
-            }
-            ConstVal::Aggregate(ConstAggregate::Tuple(fields)) |
-            ConstVal::Aggregate(ConstAggregate::Array(fields)) => {
-                for v in fields {
-                    self.compute_const(v);
-                }
-            }
-            ConstVal::Aggregate(ConstAggregate::Repeat(v, _)) => {
-                self.compute_const(v);
-            }
+            ConstVal::Value(_) => {}
             ConstVal::Unevaluated(def_id, substs) => {
                 let obligations = self.nominal_obligations(def_id, substs);
                 self.out.extend(obligations);
index 63d1f1468251b219dd87d2a04190d1f93e8c3a52..5e2792ee6410e6a1fe2d1b95aed8fca80e45ce60 100644 (file)
@@ -27,7 +27,6 @@
 use std::fmt;
 use std::usize;
 
-use rustc_const_math::ConstInt;
 use rustc_data_structures::indexed_vec::Idx;
 use syntax::abi::Abi;
 use syntax::ast::CRATE_NODE_ID;
@@ -1166,9 +1165,6 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                 TyArray(ty, sz) => {
                     print!(f, cx, write("["), print(ty), write("; "))?;
                     match sz.val {
-                        ConstVal::Integral(ConstInt::Usize(sz)) => {
-                            write!(f, "{}", sz)?;
-                        }
                         ConstVal::Value(Value::ByVal(PrimVal::Bytes(sz))) => {
                             write!(f, "{}", sz)?;
                         }
index 54457eacbf2e685e412665f6ca0035faadc09407..943de1211182c6e81a6de3da07d5f3c7bdd37ac9 100644 (file)
@@ -1088,6 +1088,13 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(trans: &TransCrate,
             stability::check_unused_or_stable_features(tcx)
         });
 
+
+        time(time_passes,
+             "MIR linting",
+             || for def_id in tcx.body_owners() {
+                 mir::const_eval::check::check(tcx, def_id)
+             });
+
         time(time_passes, "lint checking", || lint::check_crate(tcx));
 
         return Ok(f(tcx, analysis, rx, tcx.sess.compile_status()));
index 62ac898337ca9a13f083cdad8d1bf5aa5115a28d..831d4fc755f8f03490bcd76051ad790fd29e60e1 100644 (file)
@@ -682,78 +682,6 @@ fn check_attribute(&mut self, cx: &EarlyContext, attr: &ast::Attribute) {
     }
 }
 
-declare_lint! {
-    pub ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
-    Warn,
-    "floating-point literals cannot be used in patterns"
-}
-
-/// Checks for floating point literals in patterns.
-#[derive(Clone)]
-pub struct IllegalFloatLiteralPattern;
-
-impl LintPass for IllegalFloatLiteralPattern {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(ILLEGAL_FLOATING_POINT_LITERAL_PATTERN)
-    }
-}
-
-fn fl_lit_check_expr(cx: &EarlyContext, expr: &ast::Expr) {
-    use self::ast::{ExprKind, LitKind};
-    match expr.node {
-        ExprKind::Lit(ref l) => {
-            match l.node {
-                LitKind::FloatUnsuffixed(..) |
-                LitKind::Float(..) => {
-                    cx.span_lint(ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
-                                 l.span,
-                                 "floating-point literals cannot be used in patterns");
-                    },
-                _ => (),
-            }
-        }
-        // These may occur in patterns
-        // and can maybe contain float literals
-        ExprKind::Unary(_, ref f) => fl_lit_check_expr(cx, f),
-        // Other kinds of exprs can't occur in patterns so we don't have to check them
-        // (ast_validation will emit an error if they occur)
-        _ => (),
-    }
-}
-
-impl EarlyLintPass for IllegalFloatLiteralPattern {
-    fn check_pat(&mut self, cx: &EarlyContext, pat: &ast::Pat) {
-        use self::ast::PatKind;
-        pat.walk(&mut |p| {
-            match p.node {
-                // Wildcard patterns and paths are uninteresting for the lint
-                PatKind::Wild |
-                PatKind::Path(..) => (),
-
-                // The walk logic recurses inside these
-                PatKind::Ident(..) |
-                PatKind::Struct(..) |
-                PatKind::Tuple(..) |
-                PatKind::TupleStruct(..) |
-                PatKind::Ref(..) |
-                PatKind::Box(..) |
-                PatKind::Paren(..) |
-                PatKind::Slice(..) => (),
-
-                // Extract the expressions and check them
-                PatKind::Lit(ref e) => fl_lit_check_expr(cx, e),
-                PatKind::Range(ref st, ref en, _) => {
-                    fl_lit_check_expr(cx, st);
-                    fl_lit_check_expr(cx, en);
-                },
-
-                PatKind::Mac(_) => bug!("lint must run post-expansion"),
-            }
-            true
-        });
-    }
-}
-
 declare_lint! {
     pub UNUSED_DOC_COMMENT,
     Warn,
index 79f3ff9f19f65d0386ef19809b74d8a001e38a5a..e941f2e4e1c2a185441e69d6fe34b5a56eec35f4 100644 (file)
@@ -43,7 +43,6 @@
 extern crate syntax_pos;
 
 use rustc::lint;
-use rustc::middle;
 use rustc::session;
 use rustc::util;
 
@@ -107,7 +106,6 @@ macro_rules! add_lint_group {
                        UnusedParens,
                        UnusedImportBraces,
                        AnonymousParameters,
-                       IllegalFloatLiteralPattern,
                        UnusedDocComment,
                        );
 
index 926aa2a724125d3019644abef5bcc1ed32019d7e..be7f1152ea4a0300a86d3656542277952e80c074 100644 (file)
@@ -14,9 +14,6 @@
 use rustc::ty::subst::Substs;
 use rustc::ty::{self, AdtKind, Ty, TyCtxt};
 use rustc::ty::layout::{self, LayoutOf};
-use middle::const_val::ConstVal;
-use rustc_mir::const_eval::ConstContext;
-use rustc::mir::interpret::{Value, PrimVal};
 use util::nodemap::FxHashSet;
 use lint::{LateContext, LintContext, LintArray};
 use lint::{LintPass, LateLintPass};
     "literal out of range for its type"
 }
 
-declare_lint! {
-    EXCEEDING_BITSHIFTS,
-    Deny,
-    "shift exceeds the type's number of bits"
-}
-
 declare_lint! {
     VARIANT_SIZE_DIFFERENCES,
     Allow,
@@ -70,8 +61,7 @@ pub fn new() -> TypeLimits {
 impl LintPass for TypeLimits {
     fn get_lints(&self) -> LintArray {
         lint_array!(UNUSED_COMPARISONS,
-                    OVERFLOWING_LITERALS,
-                    EXCEEDING_BITSHIFTS)
+                    OVERFLOWING_LITERALS)
     }
 }
 
@@ -90,59 +80,6 @@ fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx hir::Expr) {
                                  e.span,
                                  "comparison is useless due to type limits");
                 }
-
-                if binop.node.is_shift() {
-                    let opt_ty_bits = match cx.tables.node_id_to_type(l.hir_id).sty {
-                        ty::TyInt(t) => Some(int_ty_bits(t, cx.sess().target.isize_ty)),
-                        ty::TyUint(t) => Some(uint_ty_bits(t, cx.sess().target.usize_ty)),
-                        _ => None,
-                    };
-
-                    if let Some(bits) = opt_ty_bits {
-                        let exceeding = if let hir::ExprLit(ref lit) = r.node {
-                            if let ast::LitKind::Int(shift, _) = lit.node {
-                                shift as u64 >= bits
-                            } else {
-                                false
-                            }
-                        } else {
-                            // HACK(eddyb) This might be quite inefficient.
-                            // This would be better left to MIR constant propagation,
-                            // perhaps even at trans time (like is the case already
-                            // when the value being shifted is *also* constant).
-                            let parent_item = cx.tcx.hir.get_parent(e.id);
-                            let parent_def_id = cx.tcx.hir.local_def_id(parent_item);
-                            let substs = Substs::identity_for_item(cx.tcx, parent_def_id);
-                            let const_cx = ConstContext::new(cx.tcx,
-                                                             cx.param_env.and(substs),
-                                                             cx.tables);
-                            match const_cx.eval(&r) {
-                                Ok(&ty::Const { val: ConstVal::Integral(i), .. }) => {
-                                    i.is_negative() ||
-                                    i.to_u64()
-                                        .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,
-                            }
-                        };
-                        if exceeding {
-                            cx.span_lint(EXCEEDING_BITSHIFTS,
-                                         e.span,
-                                         "bitshift exceeds the type's number of bits");
-                        }
-                    };
-                }
             }
             hir::ExprLit(ref lit) => {
                 match cx.tables.node_id_to_type(e.hir_id).sty {
@@ -301,28 +238,6 @@ fn uint_ty_range(uint_ty: ast::UintTy) -> (u128, u128) {
             }
         }
 
-        fn int_ty_bits(int_ty: ast::IntTy, isize_ty: ast::IntTy) -> u64 {
-            match int_ty {
-                ast::IntTy::Isize => int_ty_bits(isize_ty, isize_ty),
-                ast::IntTy::I8 => 8,
-                ast::IntTy::I16 => 16 as u64,
-                ast::IntTy::I32 => 32,
-                ast::IntTy::I64 => 64,
-                ast::IntTy::I128 => 128,
-            }
-        }
-
-        fn uint_ty_bits(uint_ty: ast::UintTy, usize_ty: ast::UintTy) -> u64 {
-            match uint_ty {
-                ast::UintTy::Usize => uint_ty_bits(usize_ty, usize_ty),
-                ast::UintTy::U8 => 8,
-                ast::UintTy::U16 => 16,
-                ast::UintTy::U32 => 32,
-                ast::UintTy::U64 => 64,
-                ast::UintTy::U128 => 128,
-            }
-        }
-
         fn check_limits(cx: &LateContext,
                         binop: hir::BinOp,
                         l: &hir::Expr,
index 1663cab0a592e5f473400f4597d2f384b90fa7f8..77c3eed9e44d21c069b47186dd66c48279c0fe23 100644 (file)
@@ -281,8 +281,7 @@ fn specialized_decode(&mut self) -> Result<interpret::AllocId, Self::Error> {
         let pos = self.position();
         match usize::decode(self)? {
             ::std::usize::MAX => {
-                let id = interpret_interner().reserve();
-                let alloc_id = interpret::AllocId(id);
+                let alloc_id = interpret_interner().reserve();
                 trace!("creating alloc id {:?} at {}", alloc_id, pos);
                 // insert early to allow recursive allocs
                 self.interpret_alloc_cache.insert(pos, alloc_id);
@@ -290,18 +289,12 @@ fn specialized_decode(&mut self) -> Result<interpret::AllocId, Self::Error> {
                 let allocation = interpret::Allocation::decode(self)?;
                 trace!("decoded alloc {:?} {:#?}", alloc_id, allocation);
                 let allocation = self.tcx.unwrap().intern_const_alloc(allocation);
-                interpret_interner().intern_at_reserved(id, allocation);
+                interpret_interner().intern_at_reserved(alloc_id, allocation);
 
                 let num = usize::decode(self)?;
-                let ptr = interpret::Pointer {
-                    primval: interpret::PrimVal::Ptr(interpret::MemoryPointer {
-                        alloc_id,
-                        offset: 0,
-                    }),
-                };
                 for _ in 0..num {
                     let glob = interpret::GlobalId::decode(self)?;
-                    interpret_interner().cache(glob, ptr);
+                    interpret_interner().cache(glob, alloc_id);
                 }
 
                 Ok(alloc_id)
@@ -310,7 +303,7 @@ fn specialized_decode(&mut self) -> Result<interpret::AllocId, Self::Error> {
                 trace!("creating fn alloc id at {}", pos);
                 let instance = ty::Instance::decode(self)?;
                 trace!("decoded fn alloc instance: {:?}", instance);
-                let id = interpret::AllocId(interpret_interner().create_fn_alloc(instance));
+                let id = interpret_interner().create_fn_alloc(instance);
                 trace!("created fn alloc id: {:?}", id);
                 self.interpret_alloc_cache.insert(pos, id);
                 Ok(id)
index 1e1baba2bac5e708175aa69c66501bcf3883bab6..f5631f5fab91f5988c79873a6856d717021a70a9 100644 (file)
@@ -199,26 +199,21 @@ fn specialized_encode(&mut self, alloc_id: &interpret::AllocId) -> Result<(), Se
         // 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) {
+        if let Some(alloc) = interpret_interner.get_alloc(*alloc_id) {
             trace!("encoding {:?} with {:#?}", alloc_id, alloc);
             usize::max_value().encode(self)?;
             alloc.encode(self)?;
-            let globals = interpret_interner.get_globals(interpret::Pointer {
-                primval: interpret::PrimVal::Ptr(interpret::MemoryPointer {
-                    alloc_id: *alloc_id,
-                    offset: 0,
-                }),
-            });
+            let globals = interpret_interner.get_globals(*alloc_id);
             globals.len().encode(self)?;
             for glob in globals {
                 glob.encode(self)?;
             }
-        } else if let Some(fn_instance) = interpret_interner.get_fn(alloc_id.0) {
+        } else if let Some(fn_instance) = interpret_interner.get_fn(*alloc_id) {
             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);
+            bug!("alloc id without corresponding allocation: {}", alloc_id);
         }
         Ok(())
     }
index 5955d0ca59adfe77f4f6b62bae8b4e66fee37473..182ed52961929f0e4cfa205ef17eb8c33be95b17 100644 (file)
@@ -260,12 +260,11 @@ fn sanitize_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
                 // would be lost if we just look at the normalized
                 // value.
                 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)
+                            .get_fn(p.alloc_id)
                             .map(|instance| instance.def_id())
                     },
                     ConstVal::Value(Value::ByVal(PrimVal::Undef)) => {
@@ -1044,11 +1043,8 @@ fn is_box_free(&self, operand: &Operand<'tcx>) -> bool {
                     },
                 ..
             }) => 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);
+                    let inst = self.tcx().interpret_interner.borrow().get_fn(p.alloc_id);
                     inst.map_or(false, |inst| {
                         Some(inst.def_id()) == self.tcx().lang_items().box_free_fn()
                     })
index b5b8f8d7e78b0a553d7ff105eec4e7a5d1d570a2..ca6e7c2c4158039ab8ae884de96a21ea7c03a127 100644 (file)
@@ -204,11 +204,7 @@ fn expr_as_rvalue(&mut self,
                         ty: this.hir.tcx().types.u32,
                         literal: Literal::Value {
                             value: this.hir.tcx().mk_const(ty::Const {
-                                val: if this.hir.tcx().sess.opts.debugging_opts.miri {
-                                    ConstVal::Value(Value::ByVal(PrimVal::Bytes(0)))
-                                } else {
-                                    ConstVal::Integral(ConstInt::U32(0))
-                                },
+                                val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(0))),
                                 ty: this.hir.tcx().types.u32
                             }),
                         },
@@ -406,11 +402,7 @@ fn neg_1_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
 
                 Literal::Value {
                     value: self.hir.tcx().mk_const(ty::Const {
-                        val: if self.hir.tcx().sess.opts.debugging_opts.miri {
-                            ConstVal::Value(Value::ByVal(PrimVal::Bytes(val.to_u128_unchecked())))
-                        } else {
-                            ConstVal::Integral(val)
-                        },
+                        val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(val.to_u128_unchecked()))),
                         ty
                     })
                 }
@@ -448,13 +440,9 @@ fn minval_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
 
                 Literal::Value {
                     value: self.hir.tcx().mk_const(ty::Const {
-                        val: if self.hir.tcx().sess.opts.debugging_opts.miri {
-                            ConstVal::Value(Value::ByVal(PrimVal::Bytes(
-                                val.to_u128_unchecked()
-                            )))
-                        } else {
-                            ConstVal::Integral(val)
-                        },
+                        val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(
+                            val.to_u128_unchecked()
+                        ))),
                         ty
                     })
                 }
index fafdee5b1e1b9cde3273725a92749c507a1d4e13..30c70ac30a70b5d4cc3b459bdb3dcedd92856f07 100644 (file)
@@ -299,7 +299,6 @@ pub fn perform_test(&mut self,
                 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)
@@ -310,7 +309,7 @@ pub fn perform_test(&mut self,
                                 .tcx()
                                 .interpret_interner
                                 .borrow()
-                                .get_alloc(p.alloc_id.0)
+                                .get_alloc(p.alloc_id)
                                 .map(|alloc| &alloc.bytes[..])
                         } else {
                             None
index efb367201189bd36d59c60f1119d8641aba4f6b3..78c7004ef6034070b820c9df3245fb2bb97a368b 100644 (file)
 
 use build::Builder;
 
-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;
 use syntax_pos::{Span, DUMMY_SP};
 
 impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
@@ -63,61 +61,16 @@ 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: if self.hir.tcx().sess.opts.debugging_opts.miri {
-                            ConstVal::Value(Value::ByVal(PrimVal::Bytes(0)))
-                        } else {
-                            ConstVal::Char('\0')
-                        },
+                        val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(0))),
                         ty
                     })
                 }
             }
-            ty::TyUint(ity) => {
-                let val = match ity {
-                    ast::UintTy::U8  => ConstInt::U8(0),
-                    ast::UintTy::U16 => ConstInt::U16(0),
-                    ast::UintTy::U32 => ConstInt::U32(0),
-                    ast::UintTy::U64 => ConstInt::U64(0),
-                    ast::UintTy::U128 => ConstInt::U128(0),
-                    ast::UintTy::Usize => {
-                        let uint_ty = self.hir.tcx().sess.target.usize_ty;
-                        let val = ConstUsize::new(0, uint_ty).unwrap();
-                        ConstInt::Usize(val)
-                    }
-                };
-
-                Literal::Value {
-                    value: self.hir.tcx().mk_const(ty::Const {
-                        val: if self.hir.tcx().sess.opts.debugging_opts.miri {
-                            ConstVal::Value(Value::ByVal(PrimVal::Bytes(0)))
-                        } else {
-                            ConstVal::Integral(val)
-                        },
-                        ty
-                    })
-                }
-            }
-            ty::TyInt(ity) => {
-                let val = match ity {
-                    ast::IntTy::I8  => ConstInt::I8(0),
-                    ast::IntTy::I16 => ConstInt::I16(0),
-                    ast::IntTy::I32 => ConstInt::I32(0),
-                    ast::IntTy::I64 => ConstInt::I64(0),
-                    ast::IntTy::I128 => ConstInt::I128(0),
-                    ast::IntTy::Isize => {
-                        let int_ty = self.hir.tcx().sess.target.isize_ty;
-                        let val = ConstIsize::new(0, int_ty).unwrap();
-                        ConstInt::Isize(val)
-                    }
-                };
-
+            ty::TyUint(_) |
+            ty::TyInt(_) => {
                 Literal::Value {
                     value: self.hir.tcx().mk_const(ty::Const {
-                        val: if self.hir.tcx().sess.opts.debugging_opts.miri {
-                            ConstVal::Value(Value::ByVal(PrimVal::Bytes(0)))
-                        } else {
-                            ConstVal::Integral(val)
-                        },
+                        val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(0))),
                         ty
                     })
                 }
index 9ebbc11162812ed5371a12d9f3bb9f25b2cba561..2057b0a5b4f7c19dbf14a62023e0977c9572d65e 100644 (file)
@@ -15,8 +15,6 @@
 use rustc::middle::const_val::ConstVal;
 use const_eval::eval::{compare_const_vals};
 
-use rustc_const_math::ConstInt;
-
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::indexed_vec::Idx;
 
@@ -182,20 +180,6 @@ fn lower_byte_str_pattern<'p>(&mut self, pat: &'p Pattern<'tcx>) -> Vec<&'p Patt
         let tcx = self.tcx;
         self.byte_array_map.entry(pat).or_insert_with(|| {
             match pat.kind {
-                box PatternKind::Constant {
-                    value: &ty::Const { val: ConstVal::ByteStr(b), .. }
-                } => {
-                    b.data.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::Integral(ConstInt::U8(b)),
-                                ty: tcx.types.u8
-                            })
-                        }
-                    })).collect()
-                }
                 box PatternKind::Constant {
                     value: &ty::Const { val: ConstVal::Value(b), ty }
                 } => {
@@ -209,7 +193,7 @@ fn lower_byte_str_pattern<'p>(&mut self, pat: &'p Pattern<'tcx>) -> Vec<&'p Patt
                             let alloc = tcx
                                 .interpret_interner
                                 .borrow()
-                                .get_alloc(ptr.alloc_id.0)
+                                .get_alloc(ptr.alloc_id)
                                 .unwrap();
                             assert_eq!(ptr.offset, 0);
                             // FIXME: check length
@@ -458,11 +442,7 @@ 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: if cx.tcx.sess.opts.debugging_opts.miri {
-                        ConstVal::Value(Value::ByVal(PrimVal::Bytes(b as u128)))
-                    } else {
-                        ConstVal::Bool(b)
-                    },
+                    val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(b as u128))),
                     ty: cx.tcx.types.bool
                 }))
             }).collect()
@@ -575,9 +555,6 @@ fn max_slice_length<'p, 'a: 'p, 'tcx: 'a, I>(
 
     for row in patterns {
         match *row.kind {
-            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))),
@@ -592,7 +569,7 @@ fn max_slice_length<'p, 'a: 'p, 'tcx: 'a, I>(
                     let alloc = cx.tcx
                         .interpret_interner
                         .borrow()
-                        .get_alloc(ptr.alloc_id.0)
+                        .get_alloc(ptr.alloc_id)
                         .unwrap();
                     max_fixed_len = cmp::max(max_fixed_len, alloc.bytes.len() as u64);
                 }
@@ -971,7 +948,6 @@ fn slice_pat_covered_by_constructor(tcx: TyCtxt, _span: Span,
                                     suffix: &[Pattern])
                                     -> Result<bool, ErrorReported> {
     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 }) => {
@@ -983,7 +959,7 @@ fn slice_pat_covered_by_constructor(tcx: TyCtxt, _span: Span,
             tcx
                 .interpret_interner
                 .borrow()
-                .get_alloc(ptr.alloc_id.0)
+                .get_alloc(ptr.alloc_id)
                 .unwrap()
                 .bytes
                 .as_ref()
@@ -1002,11 +978,6 @@ fn slice_pat_covered_by_constructor(tcx: TyCtxt, _span: Span,
     {
         match pat.kind {
             box PatternKind::Constant { value } => match value.val {
-                ConstVal::Integral(ConstInt::U8(u)) => {
-                    if u != *ch {
-                        return Ok(false);
-                    }
-                },
                 ConstVal::Value(Value::ByVal(PrimVal::Bytes(b))) => {
                     assert_eq!(b as u8 as u128, b);
                     if b as u8 != *ch {
@@ -1120,13 +1091,6 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
         PatternKind::Constant { value } => {
             match *constructor {
                 Slice(..) => match value.val {
-                    ConstVal::ByteStr(b) => {
-                        if wild_patterns.len() == b.data.len() {
-                            Some(cx.lower_byte_str_pattern(pat))
-                        } else {
-                            None
-                        }
-                    }
                     ConstVal::Value(Value::ByVal(PrimVal::Ptr(ptr))) => {
                         let is_array_ptr = value.ty
                             .builtin_deref(true, ty::NoPreference)
@@ -1136,7 +1100,7 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
                         let data_len = cx.tcx
                             .interpret_interner
                             .borrow()
-                            .get_alloc(ptr.alloc_id.0)
+                            .get_alloc(ptr.alloc_id)
                             .unwrap()
                             .bytes
                             .len();
diff --git a/src/librustc_mir/const_eval/check.rs b/src/librustc_mir/const_eval/check.rs
new file mode 100644 (file)
index 0000000..70435c1
--- /dev/null
@@ -0,0 +1,167 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Lints statically known runtime failures
+
+use rustc::mir::*;
+use rustc::mir::visit::Visitor;
+use rustc::mir::interpret::{Value, PrimVal};
+use rustc::middle::const_val::{ConstVal, ConstEvalErr, ErrKind};
+use rustc::traits;
+use interpret::{eval_body_as_integer, check_body};
+use rustc::ty::{TyCtxt, ParamEnv, self};
+use rustc::ty::Instance;
+use rustc::ty::layout::LayoutOf;
+use rustc::hir::def_id::DefId;
+
+pub fn check<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
+    if tcx.is_closure(def_id) {
+        return;
+    }
+    let generics = tcx.generics_of(def_id);
+    // FIXME: miri should be able to eval stuff that doesn't need info
+    // from the generics
+    if generics.parent_types as usize + generics.types.len() > 0 {
+        return;
+    }
+    let mir = &tcx.optimized_mir(def_id);
+    ConstErrVisitor {
+        tcx,
+        def_id,
+        mir,
+    }.visit_mir(mir);
+    let param_env = ParamEnv::empty(traits::Reveal::All);
+    let instance = Instance::mono(tcx, def_id);
+    for i in 0.. mir.promoted.len() {
+        use rustc_data_structures::indexed_vec::Idx;
+        check_body(tcx, instance, Some(Promoted::new(i)), param_env);
+    }
+}
+
+struct ConstErrVisitor<'a, 'tcx: 'a> {
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    def_id: DefId,
+    mir: &'a Mir<'tcx>,
+}
+
+impl<'a, 'tcx> ConstErrVisitor<'a, 'tcx> {
+    fn eval_op(&self, op: &Operand<'tcx>) -> Option<u128> {
+        let op = match *op {
+            Operand::Constant(ref c) => c,
+            _ => return None,
+        };
+        let param_env = ParamEnv::empty(traits::Reveal::All);
+        let val = match op.literal {
+            Literal::Value { value } => match value.val {
+                ConstVal::Value(Value::ByVal(PrimVal::Bytes(b))) => b,
+                _ => return None,
+            },
+            Literal::Promoted { index } => {
+                let instance = Instance::mono(self.tcx, self.def_id);
+                eval_body_as_integer(self.tcx, param_env, instance, Some(index)).unwrap()
+            }
+        };
+        Some(val)
+    }
+}
+
+impl<'a, 'tcx> Visitor<'tcx> for ConstErrVisitor<'a, 'tcx> {
+    fn visit_terminator(&mut self,
+                        block: BasicBlock,
+                        terminator: &Terminator<'tcx>,
+                        location: Location) {
+        self.super_terminator(block, terminator, location);
+        match terminator.kind {
+            TerminatorKind::Assert { cond: Operand::Constant(box Constant {
+                literal: Literal::Value {
+                    value: &ty::Const {
+                        val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(cond))),
+                    .. }
+                }, ..
+            }), expected, ref msg, .. } if (cond == 1) != expected => {
+                assert!(cond <= 1);
+                // If we know we always panic, and the error message
+                // is also constant, then we can produce a warning.
+
+                let kind = match *msg {
+                    AssertMessage::BoundsCheck { ref len, ref index } => {
+                        let len = match self.eval_op(len) {
+                            Some(val) => val,
+                            None => return,
+                        };
+                        let index = match self.eval_op(index) {
+                            Some(val) => val,
+                            None => return,
+                        };
+                        ErrKind::IndexOutOfBounds {
+                            len: len as u64,
+                            index: index as u64
+                        }
+                    }
+                    AssertMessage::Math(ref err) => ErrKind::Math(err.clone()),
+                    AssertMessage::GeneratorResumedAfterReturn |
+                    // FIXME(oli-obk): can we report a const_err warning here?
+                    AssertMessage::GeneratorResumedAfterPanic => return,
+                };
+                let span = terminator.source_info.span;
+                let msg = ConstEvalErr{ span, kind };
+                let scope_info = match self.mir.visibility_scope_info {
+                    ClearCrossCrate::Set(ref data) => data,
+                    ClearCrossCrate::Clear => return,
+                };
+                let node_id = scope_info[terminator.source_info.scope].lint_root;
+                self.tcx.lint_node(::rustc::lint::builtin::CONST_ERR,
+                            node_id,
+                            msg.span,
+                            &msg.description().into_oneline().into_owned());
+            },
+            _ => {},
+        }
+    }
+    fn visit_rvalue(&mut self,
+                    rvalue: &Rvalue<'tcx>,
+                    location: Location) {
+        self.super_rvalue(rvalue, location);
+        use rustc::mir::BinOp;
+        match *rvalue {
+            Rvalue::BinaryOp(BinOp::Shr, ref lop, ref rop) |
+            Rvalue::BinaryOp(BinOp::Shl, ref lop, ref rop) => {
+                let val = match self.eval_op(rop) {
+                    Some(val) => val,
+                    None => return,
+                };
+                let ty = lop.ty(self.mir, self.tcx);
+                let param_env = ParamEnv::empty(traits::Reveal::All);
+                let bits = (self.tcx, param_env).layout_of(ty).unwrap().size.bits();
+                if val >= bits as u128 {
+                    let data = &self.mir[location.block];
+                    let stmt_idx = location.statement_index;
+                    let source_info = if stmt_idx < data.statements.len() {
+                        data.statements[stmt_idx].source_info
+                    } else {
+                        data.terminator().source_info
+                    };
+                    let span = source_info.span;
+                    let scope_info = match self.mir.visibility_scope_info {
+                        ClearCrossCrate::Set(ref data) => data,
+                        ClearCrossCrate::Clear => return,
+                    };
+                    let node_id = scope_info[source_info.scope].lint_root;
+                    self.tcx.lint_node(
+                        ::rustc::lint::builtin::EXCEEDING_BITSHIFTS,
+                        node_id,
+                        span,
+                        "bitshift exceeds the type's number of bits");
+                }
+            }
+            _ => {}
+        }
+    }
+}
index 58fe40d12be849f467d10d369837f8dfd1fe9eaf..370b8681ba648a501122bb668cd994bac061c378 100644 (file)
@@ -9,41 +9,18 @@
 // except according to those terms.
 
 use rustc::middle::const_val::ConstVal::*;
-use rustc::middle::const_val::ConstAggregate::*;
 use rustc::middle::const_val::ErrKind::*;
-use rustc::middle::const_val::{ByteArray, ConstVal, ConstEvalErr, EvalResult, ErrKind};
+use rustc::middle::const_val::{ConstVal, ErrKind};
 
-use rustc::hir::map::blocks::FnLikeNode;
-use rustc::hir::def::{Def, CtorKind};
 use rustc::hir::def_id::DefId;
 use rustc::ty::{self, Ty, TyCtxt};
-use rustc::ty::util::IntTypeExt;
-use rustc::ty::subst::{Substs, Subst};
-use rustc::util::common::ErrorReported;
-use rustc::util::nodemap::NodeMap;
+use rustc::ty::subst::Substs;
 
-use syntax::abi::Abi;
 use syntax::ast;
-use syntax::attr;
-use rustc::hir::{self, Expr};
 
 use std::cmp::Ordering;
 
 use rustc_const_math::*;
-macro_rules! signal {
-    ($e:expr, $exn:expr) => {
-        return Err(ConstEvalErr { span: $e.span, kind: $exn })
-    }
-}
-
-macro_rules! math {
-    ($e:expr, $op:expr) => {
-        match $op {
-            Ok(val) => val,
-            Err(e) => signal!($e, ErrKind::from(e)),
-        }
-    }
-}
 
 /// * `DefId` is the id of the constant.
 /// * `Substs` is the monomorphized substitutions for the expression.
@@ -58,591 +35,94 @@ pub fn lookup_const_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     ).map(|instance| (instance.def_id(), instance.substs))
 }
 
-pub struct ConstContext<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    tables: &'a ty::TypeckTables<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    substs: &'tcx Substs<'tcx>,
-    fn_args: Option<NodeMap<&'tcx ty::Const<'tcx>>>
-}
-
-impl<'a, 'tcx> ConstContext<'a, 'tcx> {
-    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-               param_env_and_substs: ty::ParamEnvAnd<'tcx, &'tcx Substs<'tcx>>,
-               tables: &'a ty::TypeckTables<'tcx>)
-               -> Self {
-        ConstContext {
-            tcx,
-            param_env: param_env_and_substs.param_env,
-            tables,
-            substs: param_env_and_substs.value,
-            fn_args: None
-        }
-    }
-
-    /// Evaluate a constant expression in a context where the expression isn't
-    /// guaranteed to be evaluable.
-    pub fn eval(&self, e: &'tcx Expr) -> EvalResult<'tcx> {
-        if self.tables.tainted_by_errors {
-            signal!(e, TypeckError);
-        }
-        eval_const_expr_partial(self, e)
-    }
-}
-
-type CastResult<'tcx> = Result<ConstVal<'tcx>, ErrKind<'tcx>>;
-
-fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
-                                     e: &'tcx Expr) -> EvalResult<'tcx> {
-    trace!("eval_const_expr_partial: {:?}", e);
-    let tcx = cx.tcx;
-    let ty = cx.tables.expr_ty(e).subst(tcx, cx.substs);
-    let mk_const = |val| tcx.mk_const(ty::Const { val, ty });
-
-    let result = match e.node {
-      hir::ExprUnary(hir::UnNeg, ref inner) => {
-        // unary neg literals already got their sign during creation
-        if let hir::ExprLit(ref lit) = inner.node {
-            return match lit_to_const(&lit.node, tcx, ty, true) {
-                Ok(val) => Ok(mk_const(val)),
-                Err(err) => signal!(e, err),
-            };
-        }
-        mk_const(match cx.eval(inner)?.val {
-          Float(f) => Float(-f),
-          Integral(i) => Integral(math!(e, -i)),
-          _ => signal!(e, TypeckError)
-        })
-      }
-      hir::ExprUnary(hir::UnNot, ref inner) => {
-        mk_const(match cx.eval(inner)?.val {
-          Integral(i) => Integral(math!(e, !i)),
-          Bool(b) => Bool(!b),
-          _ => signal!(e, TypeckError)
-        })
-      }
-      hir::ExprUnary(hir::UnDeref, _) => signal!(e, UnimplementedConstVal("deref operation")),
-      hir::ExprBinary(op, ref a, ref b) => {
-        // technically, if we don't have type hints, but integral eval
-        // gives us a type through a type-suffix, cast or const def type
-        // we need to re-eval the other value of the BinOp if it was
-        // not inferred
-        mk_const(match (cx.eval(a)?.val, cx.eval(b)?.val) {
-          (Float(a), Float(b)) => {
-            use std::cmp::Ordering::*;
-            match op.node {
-              hir::BiAdd => Float(math!(e, a + b)),
-              hir::BiSub => Float(math!(e, a - b)),
-              hir::BiMul => Float(math!(e, a * b)),
-              hir::BiDiv => Float(math!(e, a / b)),
-              hir::BiRem => Float(math!(e, a % b)),
-              hir::BiEq => Bool(math!(e, a.try_cmp(b)) == Equal),
-              hir::BiLt => Bool(math!(e, a.try_cmp(b)) == Less),
-              hir::BiLe => Bool(math!(e, a.try_cmp(b)) != Greater),
-              hir::BiNe => Bool(math!(e, a.try_cmp(b)) != Equal),
-              hir::BiGe => Bool(math!(e, a.try_cmp(b)) != Less),
-              hir::BiGt => Bool(math!(e, a.try_cmp(b)) == Greater),
-              _ => span_bug!(e.span, "typeck error"),
-            }
-          }
-          (Integral(a), Integral(b)) => {
-            use std::cmp::Ordering::*;
-            match op.node {
-              hir::BiAdd => Integral(math!(e, a + b)),
-              hir::BiSub => Integral(math!(e, a - b)),
-              hir::BiMul => Integral(math!(e, a * b)),
-              hir::BiDiv => Integral(math!(e, a / b)),
-              hir::BiRem => Integral(math!(e, a % b)),
-              hir::BiBitAnd => Integral(math!(e, a & b)),
-              hir::BiBitOr => Integral(math!(e, a | b)),
-              hir::BiBitXor => Integral(math!(e, a ^ b)),
-              hir::BiShl => Integral(math!(e, a << b)),
-              hir::BiShr => Integral(math!(e, a >> b)),
-              hir::BiEq => Bool(math!(e, a.try_cmp(b)) == Equal),
-              hir::BiLt => Bool(math!(e, a.try_cmp(b)) == Less),
-              hir::BiLe => Bool(math!(e, a.try_cmp(b)) != Greater),
-              hir::BiNe => Bool(math!(e, a.try_cmp(b)) != Equal),
-              hir::BiGe => Bool(math!(e, a.try_cmp(b)) != Less),
-              hir::BiGt => Bool(math!(e, a.try_cmp(b)) == Greater),
-              _ => span_bug!(e.span, "typeck error"),
-            }
-          }
-          (Bool(a), Bool(b)) => {
-            Bool(match op.node {
-              hir::BiAnd => a && b,
-              hir::BiOr => a || b,
-              hir::BiBitXor => a ^ b,
-              hir::BiBitAnd => a & b,
-              hir::BiBitOr => a | b,
-              hir::BiEq => a == b,
-              hir::BiNe => a != b,
-              hir::BiLt => a < b,
-              hir::BiLe => a <= b,
-              hir::BiGe => a >= b,
-              hir::BiGt => a > b,
-              _ => span_bug!(e.span, "typeck error"),
-             })
-          }
-          (Char(a), Char(b)) => {
-            Bool(match op.node {
-              hir::BiEq => a == b,
-              hir::BiNe => a != b,
-              hir::BiLt => a < b,
-              hir::BiLe => a <= b,
-              hir::BiGe => a >= b,
-              hir::BiGt => a > b,
-              _ => span_bug!(e.span, "typeck error"),
-             })
-          }
-
-          _ => signal!(e, MiscBinaryOp),
-        })
-      }
-      hir::ExprCast(ref base, _) => {
-        let base_val = cx.eval(base)?;
-        let base_ty = cx.tables.expr_ty(base).subst(tcx, cx.substs);
-        if ty == base_ty {
-            base_val
-        } else {
-            match cast_const(tcx, base_val.val, ty) {
-                Ok(val) => mk_const(val),
-                Err(kind) => signal!(e, kind),
-            }
-        }
-      }
-      hir::ExprPath(ref qpath) => {
-        let substs = cx.tables.node_substs(e.hir_id).subst(tcx, cx.substs);
-          match cx.tables.qpath_def(qpath, e.hir_id) {
-              Def::Const(def_id) |
-              Def::AssociatedConst(def_id) => {
-                    let substs = tcx.normalize_associated_type_in_env(&substs, cx.param_env);
-                    match tcx.at(e.span).const_eval(cx.param_env.and((def_id, substs))) {
-                        Ok(val) => val,
-                        Err(ConstEvalErr { kind: TypeckError, .. }) => {
-                            signal!(e, TypeckError);
-                        }
-                        Err(err) => {
-                            debug!("bad reference: {:?}, {:?}", err.description(), err.span);
-                            signal!(e, ErroneousReferencedConstant(box err))
-                        },
-                    }
-              },
-              Def::VariantCtor(variant_def, CtorKind::Const) => {
-                mk_const(Variant(variant_def))
-              }
-              Def::VariantCtor(_, CtorKind::Fn) => {
-                  signal!(e, UnimplementedConstVal("enum variants"));
-              }
-              Def::StructCtor(_, CtorKind::Const) => {
-                  mk_const(Aggregate(Struct(&[])))
-              }
-              Def::StructCtor(_, CtorKind::Fn) => {
-                  signal!(e, UnimplementedConstVal("tuple struct constructors"))
-              }
-              Def::Local(id) => {
-                  debug!("Def::Local({:?}): {:?}", id, cx.fn_args);
-                  if let Some(&val) = cx.fn_args.as_ref().and_then(|args| args.get(&id)) {
-                      val
-                  } else {
-                      signal!(e, NonConstPath);
-                  }
-              },
-              Def::Method(id) | Def::Fn(id) => mk_const(Function(id, substs)),
-              Def::Err => span_bug!(e.span, "typeck error"),
-              _ => signal!(e, NonConstPath),
-          }
-      }
-      hir::ExprCall(ref callee, ref args) => {
-          let (def_id, substs) = match cx.eval(callee)?.val {
-              Function(def_id, substs) => (def_id, substs),
-              _ => signal!(e, TypeckError),
-          };
-
-          if tcx.fn_sig(def_id).abi() == Abi::RustIntrinsic {
-            let layout_of = |ty: Ty<'tcx>| {
-                let ty = tcx.erase_regions(&ty);
-                tcx.at(e.span).layout_of(cx.param_env.and(ty)).map_err(|err| {
-                    ConstEvalErr { span: e.span, kind: LayoutError(err) }
-                })
-            };
-            match &tcx.item_name(def_id)[..] {
-                "size_of" => {
-                    let size = layout_of(substs.type_at(0))?.size.bytes();
-                    return Ok(mk_const(Integral(Usize(ConstUsize::new(size,
-                        tcx.sess.target.usize_ty).unwrap()))));
-                }
-                "min_align_of" => {
-                    let align = layout_of(substs.type_at(0))?.align.abi();
-                    return Ok(mk_const(Integral(Usize(ConstUsize::new(align,
-                        tcx.sess.target.usize_ty).unwrap()))));
-                }
-                "type_id" => {
-                    let type_id = tcx.type_id_hash(substs.type_at(0));
-                    return Ok(mk_const(Integral(U64(type_id))));
-                }
-                _ => signal!(e, TypeckError)
-            }
-          }
-
-          let body = if let Some(node_id) = tcx.hir.as_local_node_id(def_id) {
-            if let Some(fn_like) = FnLikeNode::from_node(tcx.hir.get(node_id)) {
-                if fn_like.constness() == hir::Constness::Const {
-                    tcx.hir.body(fn_like.body())
-                } else {
-                    signal!(e, TypeckError)
-                }
-            } else {
-                signal!(e, TypeckError)
-            }
-          } else {
-            if tcx.is_const_fn(def_id) {
-                tcx.extern_const_body(def_id).body
-            } else {
-                signal!(e, TypeckError)
-            }
-          };
-
-          let arg_ids = body.arguments.iter().map(|arg| match arg.pat.node {
-               hir::PatKind::Binding(_, canonical_id, _, _) => Some(canonical_id),
-               _ => None
-           }).collect::<Vec<_>>();
-          assert_eq!(arg_ids.len(), args.len());
-
-          let mut call_args = NodeMap();
-          for (arg, arg_expr) in arg_ids.into_iter().zip(args.iter()) {
-              let arg_val = cx.eval(arg_expr)?;
-              debug!("const call arg: {:?}", arg);
-              if let Some(id) = arg {
-                assert!(call_args.insert(id, arg_val).is_none());
-              }
-          }
-          debug!("const call({:?})", call_args);
-          let callee_cx = ConstContext {
-            tcx,
-            param_env: cx.param_env,
-            tables: tcx.typeck_tables_of(def_id),
-            substs,
-            fn_args: Some(call_args)
-          };
-          callee_cx.eval(&body.value)?
-      },
-      hir::ExprLit(ref lit) => match lit_to_const(&lit.node, tcx, ty, false) {
-          Ok(val) => mk_const(val),
-          Err(err) => signal!(e, err),
-      },
-      hir::ExprBlock(ref block) => {
-        match block.expr {
-            Some(ref expr) => cx.eval(expr)?,
-            None => mk_const(Aggregate(Tuple(&[]))),
-        }
-      }
-      hir::ExprType(ref e, _) => cx.eval(e)?,
-      hir::ExprTup(ref fields) => {
-        let values = fields.iter().map(|e| cx.eval(e)).collect::<Result<Vec<_>, _>>()?;
-        mk_const(Aggregate(Tuple(tcx.alloc_const_slice(&values))))
-      }
-      hir::ExprStruct(_, ref fields, _) => {
-        mk_const(Aggregate(Struct(tcx.alloc_name_const_slice(&fields.iter().map(|f| {
-            cx.eval(&f.expr).map(|v| (f.name.node, v))
-        }).collect::<Result<Vec<_>, _>>()?))))
-      }
-      hir::ExprIndex(ref arr, ref idx) => {
-        if !tcx.features().const_indexing {
-            signal!(e, IndexOpFeatureGated);
-        }
-        let arr = cx.eval(arr)?;
-        let idx = match cx.eval(idx)?.val {
-            Integral(Usize(i)) => i.as_u64(),
-            _ => signal!(idx, IndexNotUsize),
-        };
-        assert_eq!(idx as usize as u64, idx);
-        match arr.val {
-            Aggregate(Array(v)) => {
-                if let Some(&elem) = v.get(idx as usize) {
-                    elem
-                } else {
-                    let n = v.len() as u64;
-                    signal!(e, IndexOutOfBounds { len: n, index: idx })
-                }
-            }
-
-            Aggregate(Repeat(.., n)) if idx >= n => {
-                signal!(e, IndexOutOfBounds { len: n, index: idx })
-            }
-            Aggregate(Repeat(elem, _)) => elem,
-
-            ByteStr(b) if idx >= b.data.len() as u64 => {
-                signal!(e, IndexOutOfBounds { len: b.data.len() as u64, index: idx })
-            }
-            ByteStr(b) => {
-                mk_const(Integral(U8(b.data[idx as usize])))
-            },
-
-            _ => signal!(e, IndexedNonVec),
-        }
-      }
-      hir::ExprArray(ref v) => {
-        let values = v.iter().map(|e| cx.eval(e)).collect::<Result<Vec<_>, _>>()?;
-        mk_const(Aggregate(Array(tcx.alloc_const_slice(&values))))
-      }
-      hir::ExprRepeat(ref elem, _) => {
-          let n = match ty.sty {
-            ty::TyArray(_, n) => n.val.unwrap_u64(),
-            _ => span_bug!(e.span, "typeck error")
-          };
-          mk_const(Aggregate(Repeat(cx.eval(elem)?, n)))
-      },
-      hir::ExprTupField(ref base, index) => {
-        if let Aggregate(Tuple(fields)) = cx.eval(base)?.val {
-            fields[index.node]
-        } else {
-            span_bug!(base.span, "{:#?}", cx.eval(base)?.val);
-            //signal!(base, ExpectedConstTuple);
-        }
-      }
-      hir::ExprField(ref base, field_name) => {
-        if let Aggregate(Struct(fields)) = cx.eval(base)?.val {
-            if let Some(&(_, f)) = fields.iter().find(|&&(name, _)| name == field_name.node) {
-                f
-            } else {
-                signal!(e, MissingStructField);
-            }
-        } else {
-            signal!(base, ExpectedConstStruct);
-        }
-      }
-      hir::ExprAddrOf(..) => signal!(e, UnimplementedConstVal("address operator")),
-      _ => signal!(e, MiscCatchAll)
-    };
-
-    Ok(result)
-}
-
-fn cast_const_int<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                            val: ConstInt,
-                            ty: Ty<'tcx>)
-                            -> CastResult<'tcx> {
-    let v = val.to_u128_unchecked();
-    match ty.sty {
-        ty::TyBool if v == 0 => Ok(Bool(false)),
-        ty::TyBool if v == 1 => Ok(Bool(true)),
-        ty::TyInt(ast::IntTy::I8) => Ok(Integral(I8(v as i128 as i8))),
-        ty::TyInt(ast::IntTy::I16) => Ok(Integral(I16(v as i128 as i16))),
-        ty::TyInt(ast::IntTy::I32) => Ok(Integral(I32(v as i128 as i32))),
-        ty::TyInt(ast::IntTy::I64) => Ok(Integral(I64(v as i128 as i64))),
-        ty::TyInt(ast::IntTy::I128) => Ok(Integral(I128(v as i128))),
-        ty::TyInt(ast::IntTy::Isize) => {
-            Ok(Integral(Isize(ConstIsize::new_truncating(v as i128, tcx.sess.target.isize_ty))))
-        },
-        ty::TyUint(ast::UintTy::U8) => Ok(Integral(U8(v as u8))),
-        ty::TyUint(ast::UintTy::U16) => Ok(Integral(U16(v as u16))),
-        ty::TyUint(ast::UintTy::U32) => Ok(Integral(U32(v as u32))),
-        ty::TyUint(ast::UintTy::U64) => Ok(Integral(U64(v as u64))),
-        ty::TyUint(ast::UintTy::U128) => Ok(Integral(U128(v as u128))),
-        ty::TyUint(ast::UintTy::Usize) => {
-            Ok(Integral(Usize(ConstUsize::new_truncating(v, tcx.sess.target.usize_ty))))
-        },
-        ty::TyFloat(fty) => {
-            if let Some(i) = val.to_u128() {
-                Ok(Float(ConstFloat::from_u128(i, fty)))
-            } else {
-                // The value must be negative, go through signed integers.
-                let i = val.to_u128_unchecked() as i128;
-                Ok(Float(ConstFloat::from_i128(i, fty)))
-            }
-        }
-        ty::TyRawPtr(_) => Err(ErrKind::UnimplementedConstVal("casting an address to a raw ptr")),
-        ty::TyChar => match val {
-            U8(u) => Ok(Char(u as char)),
-            _ => bug!(),
-        },
-        _ => Err(CannotCast),
-    }
-}
-
-fn cast_const_float<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                              val: ConstFloat,
-                              ty: Ty<'tcx>) -> CastResult<'tcx> {
-    let int_width = |ty| {
-        ty::layout::Integer::from_attr(tcx, ty).size().bits() as usize
-    };
-    match ty.sty {
-        ty::TyInt(ity) => {
-            if let Some(i) = val.to_i128(int_width(attr::SignedInt(ity))) {
-                cast_const_int(tcx, I128(i), ty)
-            } else {
-                Err(CannotCast)
-            }
-        }
-        ty::TyUint(uty) => {
-            if let Some(i) = val.to_u128(int_width(attr::UnsignedInt(uty))) {
-                cast_const_int(tcx, U128(i), ty)
-            } else {
-                Err(CannotCast)
-            }
-        }
-        ty::TyFloat(fty) => Ok(Float(val.convert(fty))),
-        _ => Err(CannotCast),
-    }
-}
-
-fn cast_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                        val: ConstVal<'tcx>,
-                        ty: Ty<'tcx>)
-                        -> CastResult<'tcx> {
-    match val {
-        Integral(i) => cast_const_int(tcx, i, ty),
-        Bool(b) => cast_const_int(tcx, U8(b as u8), ty),
-        Float(f) => cast_const_float(tcx, f, ty),
-        Char(c) => cast_const_int(tcx, U32(c as u32), ty),
-        Variant(v) => {
-            let adt = tcx.adt_def(tcx.parent_def_id(v).unwrap());
-            let idx = adt.variant_index_with_id(v);
-            cast_const_int(tcx, adt.discriminant_for_variant(tcx, idx), ty)
-        }
-        Function(..) => Err(UnimplementedConstVal("casting fn pointers")),
-        ByteStr(b) => match ty.sty {
-            ty::TyRawPtr(_) => {
-                Err(ErrKind::UnimplementedConstVal("casting a bytestr to a raw ptr"))
-            },
-            ty::TyRef(_, ty::TypeAndMut { ref ty, mutbl: hir::MutImmutable }) => match ty.sty {
-                ty::TyArray(ty, n) => {
-                    let n = n.val.unwrap_u64();
-                    if ty == tcx.types.u8 && n == b.data.len() as u64 {
-                        Ok(val)
-                    } else {
-                        Err(CannotCast)
-                    }
-                }
-                ty::TySlice(_) => {
-                    Err(ErrKind::UnimplementedConstVal("casting a bytestr to slice"))
-                },
-                _ => Err(CannotCast),
-            },
-            _ => Err(CannotCast),
-        },
-        Str(s) => match ty.sty {
-            ty::TyRawPtr(_) => Err(ErrKind::UnimplementedConstVal("casting a str to a raw ptr")),
-            ty::TyRef(_, ty::TypeAndMut { ref ty, mutbl: hir::MutImmutable }) => match ty.sty {
-                ty::TyStr => Ok(Str(s)),
-                _ => Err(CannotCast),
-            },
-            _ => Err(CannotCast),
-        },
-        _ => Err(CannotCast),
-    }
-}
-
 pub fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind,
                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                          mut ty: Ty<'tcx>,
+                          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)
-        }
-    }
-
-    match *lit {
-        LitKind::Str(ref s, _) => Ok(Str(s.as_str())),
-        LitKind::ByteStr(ref data) => Ok(ByteStr(ByteArray { data })),
-        LitKind::Byte(n) => Ok(Integral(U8(n))),
-        LitKind::Int(n, hint) => {
-            match (&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!()
-            }
-        }
+    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(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(id, 0);
+            Value::ByVal(PrimVal::Ptr(ptr))
+        },
+        LitKind::Byte(n) => Value::ByVal(PrimVal::Bytes(n as u128)),
+        LitKind::Int(n, _) => {
+            enum Int {
+                Signed(IntTy),
+                Unsigned(UintTy),
+            }
+            let ty = match ty.sty {
+                ty::TyInt(IntTy::Isize) => Int::Signed(tcx.sess.target.isize_ty),
+                ty::TyInt(other) => Int::Signed(other),
+                ty::TyUint(UintTy::Usize) => Int::Unsigned(tcx.sess.target.usize_ty),
+                ty::TyUint(other) => Int::Unsigned(other),
+                _ => bug!(),
+            };
+            let n = match ty {
+                // FIXME(oli-obk): are these casts correct?
+                Int::Signed(IntTy::I8) if neg =>
+                    (n as i128 as i8).overflowing_neg().0 as i128 as u128,
+                Int::Signed(IntTy::I16) if neg =>
+                    (n as i128 as i16).overflowing_neg().0 as i128 as u128,
+                Int::Signed(IntTy::I32) if neg =>
+                    (n as i128 as i32).overflowing_neg().0 as i128 as u128,
+                Int::Signed(IntTy::I64) if neg =>
+                    (n as i128 as i64).overflowing_neg().0 as i128 as u128,
+                Int::Signed(IntTy::I128) if neg =>
+                    (n as i128).overflowing_neg().0 as u128,
+                Int::Signed(IntTy::I8) => n as i128 as i8 as i128 as u128,
+                Int::Signed(IntTy::I16) => n as i128 as i16 as i128 as u128,
+                Int::Signed(IntTy::I32) => n as i128 as i32 as i128 as u128,
+                Int::Signed(IntTy::I64) => n as i128 as i64 as i128 as u128,
+                Int::Signed(IntTy::I128) => n,
+                Int::Unsigned(UintTy::U8) => n as u8 as u128,
+                Int::Unsigned(UintTy::U16) => n as u16 as u128,
+                Int::Unsigned(UintTy::U32) => n as u32 as u128,
+                Int::Unsigned(UintTy::U64) => n as u64 as u128,
+                Int::Unsigned(UintTy::U128) => n,
+                _ => bug!(),
+            };
+            Value::ByVal(PrimVal::Bytes(n))
+        },
         LitKind::Float(n, fty) => {
-            let mut f = parse_float(&n.as_str(), fty)?;
+            let n = n.as_str();
+            let mut f = parse_float(&n, fty)?;
             if neg {
                 f = -f;
             }
-            Ok(Float(f))
+            let bits = f.bits;
+            Value::ByVal(PrimVal::Bytes(bits))
         }
         LitKind::FloatUnsuffixed(n) => {
             let fty = match ty.sty {
                 ty::TyFloat(fty) => fty,
                 _ => bug!()
             };
-            let mut f = parse_float(&n.as_str(), fty)?;
+            let n = n.as_str();
+            let mut f = parse_float(&n, fty)?;
             if neg {
                 f = -f;
             }
-            Ok(Float(f))
+            let bits = f.bits;
+            Value::ByVal(PrimVal::Bytes(bits))
         }
-        LitKind::Bool(b) => Ok(Bool(b)),
-        LitKind::Char(c) => Ok(Char(c)),
-    }
+        LitKind::Bool(b) => Value::ByVal(PrimVal::Bytes(b as u128)),
+        LitKind::Char(c) => Value::ByVal(PrimVal::Bytes(c as u128)),
+    };
+    Ok(ConstVal::Value(lit))
 }
 
 fn parse_float<'tcx>(num: &str, fty: ast::FloatTy)
@@ -657,41 +137,26 @@ 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(),
-        (&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)
-            })
+            match ty.sty {
+                ty::TyFloat(ty) => {
+                    let l = ConstFloat {
+                        bits: a,
+                        ty,
+                    };
+                    let r = ConstFloat {
+                        bits: b,
+                        ty,
+                    };
+                    // FIXME(oli-obk): report cmp errors?
+                    l.try_cmp(r).ok()
+                },
+                ty::TyInt(_) => Some((a as i128).cmp(&(b as i128))),
+                _ => Some(a.cmp(&b)),
+            }
         },
         _ if a == b => Some(Ordering::Equal),
         _ => None,
     }
 }
-
-impl<'a, 'tcx> ConstContext<'a, 'tcx> {
-    pub fn compare_lit_exprs(&self,
-                             a: &'tcx Expr,
-                             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) => {
-                e.report(tcx, a.span, "expression");
-                return Err(ErrorReported);
-            }
-        };
-        let b = match self.eval(b) {
-            Ok(b) => b,
-            Err(e) => {
-                e.report(tcx, b.span, "expression");
-                return Err(ErrorReported);
-            }
-        };
-        Ok(compare_const_vals(&a.val, &b.val, ty))
-    }
-}
index 27356c2b0821f05b13c0c5b4a3208db711b6eee3..f47dc61c27c4d86808a56955a74067f9d2eb97f5 100644 (file)
@@ -14,5 +14,6 @@
 mod _match;
 pub mod check_match;
 pub mod pattern;
+pub mod check;
 
 pub use self::eval::*;
index 48822c506aef27e1a405194b534c3d786b44fb9c..48438e7dbfd58ee1cdce92156598a55262380059 100644 (file)
@@ -8,10 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use const_eval::eval;
 use interpret::{const_val_field, const_discr};
 
-use rustc::middle::const_val::{ConstEvalErr, ConstVal, ConstAggregate};
+use rustc::middle::const_val::{ConstEvalErr, ErrKind, ConstVal};
 use rustc::mir::{Field, BorrowKind, Mutability};
 use rustc::mir::interpret::{Value, PrimVal};
 use rustc::ty::{self, TyCtxt, AdtDef, Ty, Region};
@@ -19,6 +18,7 @@
 use rustc::hir::{self, PatKind, RangeEnd};
 use rustc::hir::def::{Def, CtorKind};
 use rustc::hir::pat_util::EnumerateAndAdjustIterator;
+use const_eval::eval::compare_const_vals;
 
 use rustc_data_structures::indexed_vec::Idx;
 
@@ -114,16 +114,7 @@ pub enum PatternKind<'tcx> {
 
 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::Unevaluated(..) => bug!("{:?} not printable in a pattern", value)
     }
 }
@@ -366,10 +357,27 @@ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat) -> Pattern<'tcx> {
 
             PatKind::Lit(ref value) => self.lower_lit(value),
 
-            PatKind::Range(ref lo, ref hi, end) => {
-                match (self.lower_lit(lo), self.lower_lit(hi)) {
+            PatKind::Range(ref lo_expr, ref hi_expr, end) => {
+                match (self.lower_lit(lo_expr), self.lower_lit(hi_expr)) {
                     (PatternKind::Constant { value: lo },
                      PatternKind::Constant { value: hi }) => {
+                        use std::cmp::Ordering;
+                        match (end, compare_const_vals(&lo.val, &hi.val, ty).unwrap()) {
+                            (RangeEnd::Excluded, Ordering::Less) => {},
+                            (RangeEnd::Excluded, _) => span_err!(
+                                self.tcx.sess,
+                                lo_expr.span,
+                                E0579,
+                                "lower range bound must be less than upper",
+                            ),
+                            (RangeEnd::Included, Ordering::Greater) => {
+                                struct_span_err!(self.tcx.sess, lo_expr.span, E0030,
+                                    "lower range bound must be less than or equal to upper")
+                                    .span_label(lo_expr.span, "lower bound larger than upper bound")
+                                    .emit();
+                            },
+                            (RangeEnd::Included, _) => {}
+                        }
                         PatternKind::Range { lo, hi, end }
                     }
                     _ => PatternKind::Wild
@@ -487,7 +495,7 @@ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat) -> Pattern<'tcx> {
                                        pattern: self.lower_pattern(field),
                                    })
                                    .collect();
-                self.lower_variant_or_leaf(def, ty, subpatterns)
+                self.lower_variant_or_leaf(def, pat.span, ty, subpatterns)
             }
 
             PatKind::Struct(ref qpath, ref fields, _) => {
@@ -519,7 +527,7 @@ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat) -> Pattern<'tcx> {
                           })
                           .collect();
 
-                self.lower_variant_or_leaf(def, ty, subpatterns)
+                self.lower_variant_or_leaf(def, pat.span, ty, subpatterns)
             }
         };
 
@@ -610,6 +618,7 @@ fn slice_or_array_pattern(
     fn lower_variant_or_leaf(
         &mut self,
         def: Def,
+        span: Span,
         ty: Ty<'tcx>,
         subpatterns: Vec<FieldPattern<'tcx>>)
         -> PatternKind<'tcx>
@@ -640,7 +649,13 @@ fn lower_variant_or_leaf(
                 PatternKind::Leaf { subpatterns: subpatterns }
             }
 
-            _ => bug!()
+            _ => {
+                self.errors.push(PatternError::ConstEval(ConstEvalErr {
+                    span,
+                    kind: ErrKind::NonConstPath,
+                }));
+                PatternKind::Wild
+            }
         }
     }
 
@@ -660,18 +675,13 @@ fn lower_path(&mut self,
                 let substs = self.tables.node_substs(id);
                 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)
+                        return self.const_to_pat(instance, value, id, span)
                     },
                     Err(e) => {
                         self.errors.push(PatternError::ConstEval(e));
@@ -679,7 +689,7 @@ fn lower_path(&mut self,
                     }
                 }
             }
-            _ => self.lower_variant_or_leaf(def, ty, vec![]),
+            _ => self.lower_variant_or_leaf(def, span, ty, vec![]),
         };
 
         Pattern {
@@ -690,68 +700,51 @@ 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 super::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 super::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
-                        },
-                    }
+        match expr.node {
+            hir::ExprLit(ref lit) => {
+                let ty = self.tables.expr_ty(expr);
+                match super::eval::lit_to_const(&lit.node, self.tcx, ty, false) {
+                    Ok(val) => {
+                        let instance = ty::Instance::new(
+                            self.tables.local_id_root.expect("literal outside any scope"),
+                            self.substs,
+                        );
+                        let cv = self.tcx.mk_const(ty::Const { val, ty });
+                        *self.const_to_pat(instance, cv, expr.hir_id, lit.span).kind
+                    },
+                    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);
-        match const_cx.eval(expr) {
-            Ok(value) => {
-                if let ConstVal::Variant(def_id) = value.val {
-                    let ty = self.tables.expr_ty(expr);
-                    self.lower_variant_or_leaf(Def::Variant(def_id), ty, vec![])
-                } else {
-                    PatternKind::Constant { value }
+            },
+            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 super::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
+                    },
                 }
             }
-            Err(e) => {
-                self.errors.push(PatternError::ConstEval(e));
-                PatternKind::Wild
-            }
+            _ => span_bug!(expr.span, "not a literal: {:?}", expr),
         }
     }
 
@@ -759,14 +752,23 @@ fn const_to_pat(
         &self,
         instance: ty::Instance<'tcx>,
         cv: &'tcx ty::Const<'tcx>,
+        id: hir::HirId,
         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
-            }
+                let id = self.tcx.hir.hir_to_node_id(id);
+                self.tcx.lint_node(
+                    ::rustc::lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
+                    id,
+                    span,
+                    "floating-point types cannot be used in patterns",
+                );
+                PatternKind::Constant {
+                    value: cv,
+                }
+            },
             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");
@@ -803,30 +805,18 @@ fn const_to_pat(
                                 let field = Field::new(i);
                                 let val = match cv.val {
                                     ConstVal::Value(miri) => const_val_field(
-                                        self.tcx, self.param_env, instance, Some(variant_index), field, miri, cv.ty,
+                                        self.tcx, self.param_env, instance,
+                                        Some(variant_index), field, miri, cv.ty,
                                     ).unwrap(),
                                     _ => bug!("{:#?} is not a valid tuple", cv),
                                 };
                                 FieldPattern {
                                     field,
-                                    pattern: self.const_to_pat(instance, val, span),
+                                    pattern: self.const_to_pat(instance, val, id, 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,
@@ -839,12 +829,9 @@ fn const_to_pat(
             ty::TyAdt(adt_def, _) => {
                 let struct_var = adt_def.struct_variant();
                 PatternKind::Leaf {
-                    subpatterns: struct_var.fields.iter().enumerate().map(|(i, f)| {
+                    subpatterns: struct_var.fields.iter().enumerate().map(|(i, _)| {
                         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) => const_val_field(
                                 self.tcx, self.param_env, instance, None, field, miri, cv.ty,
                             ).unwrap(),
@@ -852,7 +839,7 @@ fn const_to_pat(
                         };
                         FieldPattern {
                             field,
-                            pattern: self.const_to_pat(instance, val, span),
+                            pattern: self.const_to_pat(instance, val, id, span),
                         }
                     }).collect()
                 }
@@ -862,7 +849,6 @@ fn const_to_pat(
                     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) => const_val_field(
                                 self.tcx, self.param_env, instance, None, field, miri, cv.ty,
                             ).unwrap(),
@@ -870,29 +856,26 @@ fn const_to_pat(
                         };
                         FieldPattern {
                             field,
-                            pattern: self.const_to_pat(instance, val, span),
+                            pattern: self.const_to_pat(instance, val, id, span),
                         }
                     }).collect()
                 }
             }
             ty::TyArray(_, n) => {
-                PatternKind::Leaf {
-                    subpatterns: (0..n.val.unwrap_u64()).map(|i| {
+                PatternKind::Array {
+                    prefix: (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) => const_val_field(
                                 self.tcx, self.param_env, instance, None, field, miri, cv.ty,
                             ).unwrap(),
                             _ => bug!("{:#?} is not a valid tuple", cv),
                         };
-                        FieldPattern {
-                            field,
-                            pattern: self.const_to_pat(instance, val, span),
-                        }
-                    }).collect()
+                        self.const_to_pat(instance, val, id, span)
+                    }).collect(),
+                    slice: None,
+                    suffix: Vec::new(),
                 }
             }
             _ => {
index d71298fb1a6f5ec77b131093b95bccf36e4d5b92..f2533276645972a3c769d9ba83a0d016c98a9751 100644 (file)
@@ -325,6 +325,24 @@ struct X { x: (), }
 ```
 "##,
 
+E0030: r##"
+When matching against a range, the compiler verifies that the range is
+non-empty.  Range patterns include both end-points, so this is equivalent to
+requiring the start of the range to be less than or equal to the end of the
+range.
+
+For example:
+
+```compile_fail
+match 5u32 {
+    // This range is ok, albeit pointless.
+    1 ... 1 => {}
+    // This range is empty, and the compiler can tell.
+    1000 ... 5 => {}
+}
+```
+"##,
+
 E0158: r##"
 `const` and `static` mean different things. A `const` is a compile-time
 constant, an alias for a literal value. This property means you can match it
@@ -2160,6 +2178,24 @@ fn main() {
 ```
 "##,
 
+E0579: r##"
+When matching against an exclusive range, the compiler verifies that the range
+is non-empty. Exclusive range patterns include the start point but not the end
+point, so this is equivalent to requiring the start of the range to be less
+than the end of the range.
+
+For example:
+
+```compile_fail
+match 5u32 {
+    // This range is ok, albeit pointless.
+    1 .. 2 => {}
+    // This range is empty, and the compiler can tell.
+    5 .. 5 => {}
+}
+```
+"##,
+
 E0595: r##"
 Closures cannot mutate immutable captured variables.
 
index 198e55358e7ee5f01fe61d2015ce3ae570b1fd15..e65f8f3f683f194440ad04d6e3ddeeec8a2bdf4a 100644 (file)
@@ -637,7 +637,7 @@ fn method_callee<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
         kind: ExprKind::Literal {
             literal: Literal::Value {
                 value: cx.tcx().mk_const(ty::Const {
-                    val: const_fn(cx.tcx, def_id, substs),
+                    val: ConstVal::Value(Value::ByVal(PrimVal::Undef)),
                     ty
                 }),
             },
@@ -677,28 +677,6 @@ 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)
@@ -706,13 +684,13 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
     let substs = cx.tables().node_substs(expr.hir_id);
     match def {
         // A regular function, constructor function or a constant.
-        Def::Fn(def_id) |
-        Def::Method(def_id) |
-        Def::StructCtor(def_id, CtorKind::Fn) |
-        Def::VariantCtor(def_id, CtorKind::Fn) => ExprKind::Literal {
+        Def::Fn(_) |
+        Def::Method(_) |
+        Def::StructCtor(_, CtorKind::Fn) |
+        Def::VariantCtor(_, CtorKind::Fn) => ExprKind::Literal {
             literal: Literal::Value {
                 value: cx.tcx.mk_const(ty::Const {
-                    val: const_fn(cx.tcx.global_tcx(), def_id, substs),
+                    val: ConstVal::Value(Value::ByVal(PrimVal::Undef)),
                     ty: cx.tables().node_id_to_type(expr.hir_id)
                 }),
             },
index 7ebed0bbddbf581996ec01c4f7b2c18b0b6bcaae..6fda4703d1cbc7cb0121a3ff370012a5b94052e9 100644 (file)
@@ -25,7 +25,7 @@
 use rustc::ty::subst::Subst;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::subst::Substs;
-use syntax::ast;
+use syntax::ast::{self, LitKind};
 use syntax::attr;
 use syntax::symbol::Symbol;
 use rustc::hir;
@@ -119,11 +119,7 @@ pub fn usize_literal(&mut self, value: u64) -> Literal<'tcx> {
             Ok(val) => {
                 Literal::Value {
                     value: self.tcx.mk_const(ty::Const {
-                        val: if self.tcx.sess.opts.debugging_opts.miri {
-                            ConstVal::Value(Value::ByVal(PrimVal::Bytes(value as u128)))
-                        } else {
-                            ConstVal::Integral(ConstInt::Usize(val))
-                        },
+                        val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(val.as_u64() as u128))),
                         ty: self.tcx.types.usize
                     })
                 }
@@ -143,11 +139,7 @@ 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: if self.tcx.sess.opts.debugging_opts.miri {
-                    ConstVal::Value(Value::ByVal(PrimVal::Bytes(1)))
-                } else {
-                    ConstVal::Bool(true)
-                },
+                val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(1))),
                 ty: self.tcx.types.bool
             })
         }
@@ -156,11 +148,7 @@ 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: if self.tcx.sess.opts.debugging_opts.miri {
-                    ConstVal::Value(Value::ByVal(PrimVal::Bytes(0)))
-                } else {
-                    ConstVal::Bool(false)
-                },
+                val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(0))),
                 ty: self.tcx.types.bool
             })
         }
@@ -175,13 +163,6 @@ pub fn const_eval_literal(
     ) -> Literal<'tcx> {
         let tcx = self.tcx.global_tcx();
 
-        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
@@ -189,128 +170,59 @@ pub fn const_eval_literal(
             })
         };
 
-        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;
-
+        use rustc::mir::interpret::*;
         let lit = match *lit {
-            LitKind::Str(ref s, _) => Ok(Str(s.as_str())),
+            LitKind::Str(ref s, _) => {
+                let s = s.as_str();
+                let id = self.tcx.allocate_cached(s.as_bytes());
+                let ptr = MemoryPointer::new(id, 0);
+                Value::ByValPair(
+                    PrimVal::Ptr(ptr),
+                    PrimVal::from_u128(s.len() as u128),
+                )
+            },
             LitKind::ByteStr(ref data) => {
-                let data: &'tcx [u8] = data;
-                Ok(ByteStr(ByteArray { data }))
+                let id = self.tcx.allocate_cached(data);
+                let ptr = MemoryPointer::new(id, 0);
+                Value::ByVal(PrimVal::Ptr(ptr))
             },
-            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::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 mut f = parse_float(&n.as_str(), fty);
+                let n = n.as_str();
+                let mut f = parse_float(&n, fty);
                 if neg {
                     f = -f;
                 }
-                Ok(ConstVal::Float(f))
+                let bits = f.bits;
+                Value::ByVal(PrimVal::Bytes(bits))
             }
             LitKind::FloatUnsuffixed(n) => {
                 let fty = match ty.sty {
                     ty::TyFloat(fty) => fty,
                     _ => bug!()
                 };
-                let mut f = parse_float(&n.as_str(), fty);
+                let n = n.as_str();
+                let mut f = parse_float(&n, fty);
                 if neg {
                     f = -f;
                 }
-                Ok(ConstVal::Float(f))
+                let bits = f.bits;
+                Value::ByVal(PrimVal::Bytes(bits))
             }
-            LitKind::Bool(b) => Ok(Bool(b)),
-            LitKind::Char(c) => Ok(Char(c)),
+            LitKind::Bool(b) => Value::ByVal(PrimVal::Bytes(b as u128)),
+            LitKind::Char(c) => Value::ByVal(PrimVal::Bytes(c as u128)),
         };
-
-        match lit {
-            Ok(value) => Literal::Value { value: self.tcx.mk_const(ty::Const {
-                val: value,
+        Literal::Value {
+            value: self.tcx.mk_const(ty::Const {
+                val: ConstVal::Value(lit),
                 ty,
-            }) },
-            Err(kind) => self.fatal_const_eval_err(&ConstEvalErr {
-                span: sp,
-                kind,
-            }, sp, "expression")
+            }),
         }
     }
 
@@ -352,12 +264,8 @@ pub fn trait_method(&mut self,
                 return (method_ty,
                         Literal::Value {
                             value: self.tcx.mk_const(ty::Const {
-                                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)
-                                },
+                                // ZST function type
+                                val: ConstVal::Value(Value::ByVal(PrimVal::Undef)),
                                 ty: method_ty
                             }),
                         });
index 3a9149b44bba7146632439e055c2cc467c13ec9f..6929bccaa9500e5e7c7116a8be594dbed779f99c 100644 (file)
@@ -5,17 +5,13 @@
 use rustc::mir;
 use rustc::middle::const_val::ErrKind::{CheckMatchError, TypeckError};
 use rustc::middle::const_val::{ConstEvalErr, ConstVal};
-use const_eval::{lookup_const_by_id, ConstContext};
-use rustc::mir::Field;
-use rustc_data_structures::indexed_vec::Idx;
+use const_eval::lookup_const_by_id;
 
 use syntax::ast::Mutability;
 use syntax::codemap::Span;
 
 use rustc::mir::interpret::{EvalResult, EvalError, EvalErrorKind, GlobalId, Value, MemoryPointer, Pointer, PrimVal};
-use super::{Place, EvalContext, StackPopCleanup, ValTy, HasMemory, PlaceExtra};
-
-use rustc_const_math::ConstInt;
+use super::{Place, EvalContext, StackPopCleanup, ValTy, PlaceExtra};
 
 use std::fmt;
 use std::error::Error;
@@ -43,93 +39,89 @@ pub fn mk_eval_cx<'a, 'tcx>(
 pub fn eval_body<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     instance: Instance<'tcx>,
+    promoted: Option<mir::Promoted>,
     param_env: ty::ParamEnv<'tcx>,
 ) -> EvalResult<'tcx, (Value, Pointer, Ty<'tcx>)> {
+    eval_body_and_ecx(tcx, instance, promoted, param_env).0
+}
+
+pub fn check_body<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    instance: Instance<'tcx>,
+    promoted: Option<mir::Promoted>,
+    param_env: ty::ParamEnv<'tcx>,
+) {
+    let (res, ecx) = eval_body_and_ecx(tcx, instance, promoted, param_env);
+    if let Err(mut err) = res {
+        ecx.report(&mut err);
+    }
+}
+
+fn eval_body_and_ecx<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    instance: Instance<'tcx>,
+    promoted: Option<mir::Promoted>,
+    param_env: ty::ParamEnv<'tcx>,
+) -> (EvalResult<'tcx, (Value, Pointer, Ty<'tcx>)>, EvalContext<'a, 'tcx, CompileTimeEvaluator>) {
     debug!("eval_body: {:?}, {:?}", instance, param_env);
     let limits = super::ResourceLimits::default();
     let mut ecx = EvalContext::new(tcx, param_env, limits, CompileTimeEvaluator, ());
     let cid = GlobalId {
         instance,
-        promoted: None,
+        promoted,
     };
 
-    if ecx.tcx.has_attr(instance.def_id(), "linkage") {
-        return Err(ConstEvalError::NotConst("extern global".to_string()).into());
-    }
-    let instance_ty = instance.ty(tcx);
-    if tcx.interpret_interner.borrow().get_cached(cid).is_none() {
-        let mir = ecx.load_mir(instance.def)?;
-        let layout = ecx.layout_of(instance_ty)?;
-        assert!(!layout.is_unsized());
-        let ptr = ecx.memory.allocate(
-            layout.size.bytes(),
-            layout.align,
-            None,
-        )?;
-        tcx.interpret_interner.borrow_mut().cache(cid, ptr.alloc_id);
-        let cleanup = StackPopCleanup::MarkStatic(Mutability::Immutable);
-        let name = ty::tls::with(|tcx| tcx.item_path_str(instance.def_id()));
-        trace!("const_eval: pushing stack frame for global: {}", name);
-        ecx.push_stack_frame(
-            instance,
-            mir.span,
-            mir,
-            Place::from_ptr(ptr, layout.align),
-            cleanup.clone(),
-        )?;
-
-        while ecx.step()? {}
-    }
-    let alloc = tcx.interpret_interner.borrow().get_cached(cid).expect("global not cached");
-    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))
+    let res = (|| {
+        if ecx.tcx.has_attr(instance.def_id(), "linkage") {
+            return Err(ConstEvalError::NotConst("extern global".to_string()).into());
+        }
+        let instance_ty = instance.ty(tcx);
+        if tcx.interpret_interner.borrow().get_cached(cid).is_none() {
+            let mir = ecx.load_mir(instance.def)?;
+            let layout = ecx.layout_of(instance_ty)?;
+            assert!(!layout.is_unsized());
+            let ptr = ecx.memory.allocate(
+                layout.size.bytes(),
+                layout.align,
+                None,
+            )?;
+            tcx.interpret_interner.borrow_mut().cache(cid, ptr.alloc_id);
+            let cleanup = StackPopCleanup::MarkStatic(Mutability::Immutable);
+            let name = ty::tls::with(|tcx| tcx.item_path_str(instance.def_id()));
+            trace!("const_eval: pushing stack frame for global: {}", name);
+            ecx.push_stack_frame(
+                instance,
+                mir.span,
+                mir,
+                Place::from_ptr(ptr, layout.align),
+                cleanup.clone(),
+            )?;
+
+            while ecx.step()? {}
+        }
+        let alloc = tcx.interpret_interner.borrow().get_cached(cid).expect("global not cached");
+        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))
+    })();
+    (res, ecx)
 }
 
 pub fn eval_body_as_integer<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     instance: Instance<'tcx>,
-) -> EvalResult<'tcx, ConstInt> {
-    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};
-    use rustc::ty::TypeVariants::*;
-    use rustc_const_math::{ConstIsize, ConstUsize};
-    Ok(match ty.sty {
-        TyInt(IntTy::I8) => ConstInt::I8(prim as i128 as i8),
-        TyInt(IntTy::I16) => ConstInt::I16(prim as i128 as i16),
-        TyInt(IntTy::I32) => ConstInt::I32(prim as i128 as i32),
-        TyInt(IntTy::I64) => ConstInt::I64(prim as i128 as i64),
-        TyInt(IntTy::I128) => ConstInt::I128(prim as i128),
-        TyInt(IntTy::Isize) => ConstInt::Isize(
-            ConstIsize::new(prim as i128 as i64, tcx.sess.target.isize_ty)
-                .expect("miri should already have errored"),
-        ),
-        TyUint(UintTy::U8) => ConstInt::U8(prim as u8),
-        TyUint(UintTy::U16) => ConstInt::U16(prim as u16),
-        TyUint(UintTy::U32) => ConstInt::U32(prim as u32),
-        TyUint(UintTy::U64) => ConstInt::U64(prim as u64),
-        TyUint(UintTy::U128) => ConstInt::U128(prim),
-        TyUint(UintTy::Usize) => ConstInt::Usize(
-            ConstUsize::new(prim as u64, tcx.sess.target.usize_ty)
-                .expect("miri should already have errored"),
-        ),
-        _ => {
-            return Err(
-                ConstEvalError::NeedsRfc(
-                    "evaluating anything other than isize/usize during typeck".to_string(),
-                ).into(),
-            )
-        }
-    })
+    promoted: Option<mir::Promoted>,
+) -> EvalResult<'tcx, u128> {
+    let (value, _, ty) = eval_body(tcx, instance, promoted, param_env)?;
+    match value {
+        Value::ByVal(prim) => prim.to_bytes(),
+        _ => err!(TypeNotPrimitive(ty)),
+    }
 }
 
 pub struct CompileTimeEvaluator;
@@ -337,7 +329,7 @@ fn const_val_field_inner<'a, 'tcx>(
     trace!("const_val_field: {:?}, {:?}, {:?}, {:?}", instance, field, value, ty);
     let mut ecx = mk_eval_cx(tcx, instance, 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::ByValPair(..) | Value::ByVal(_) => ecx.read_field(value, variant, field, ty)?.expect("const_val_field on non-field"),
         Value::ByRef(ptr, align) => {
             let place = Place::Ptr {
                 ptr,
@@ -422,248 +414,13 @@ pub fn const_eval_provider<'a, 'tcx>(
 
 
     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);
-    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,
+    match ::interpret::eval_body(tcx, instance, None, 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)) => 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)
-        }
-    }
-}
-
-fn check_ctfe_against_miri<'a, 'tcx>(
-    ecx: &mut EvalContext<'a, 'tcx, CompileTimeEvaluator>,
-    miri_place: Place,
-    miri_ty: Ty<'tcx>,
-    ctfe: ConstVal<'tcx>,
-) {
-    use rustc::middle::const_val::ConstAggregate::*;
-    use rustc_const_math::ConstFloat;
-    use rustc::ty::TypeVariants::*;
-    let miri_val = ValTy {
-        value: ecx.read_place(miri_place).unwrap(),
-        ty: miri_ty
-    };
-    match miri_ty.sty {
-        TyInt(int_ty) => {
-            let prim = get_prim(ecx, miri_val);
-            let c = ConstInt::new_signed_truncating(prim as i128,
-                                                    int_ty,
-                                                    ecx.tcx.sess.target.isize_ty);
-            let c = ConstVal::Integral(c);
-            assert_eq!(c, ctfe, "miri evaluated to {:?}, but ctfe yielded {:?}", c, ctfe);
-        },
-        TyUint(uint_ty) => {
-            let prim = get_prim(ecx, miri_val);
-            let c = ConstInt::new_unsigned_truncating(prim,
-                                                     uint_ty,
-                                                     ecx.tcx.sess.target.usize_ty);
-            let c = ConstVal::Integral(c);
-            assert_eq!(c, ctfe, "miri evaluated to {:?}, but ctfe yielded {:?}", c, ctfe);
-        },
-        TyFloat(ty) => {
-            let prim = get_prim(ecx, miri_val);
-            let f = ConstVal::Float(ConstFloat { bits: prim, ty });
-            assert_eq!(f, ctfe, "miri evaluated to {:?}, but ctfe yielded {:?}", f, ctfe);
-        },
-        TyBool => {
-            let bits = get_prim(ecx, miri_val);
-            if bits > 1 {
-                bug!("miri evaluated to {}, but expected a bool {:?}", bits, ctfe);
-            }
-            let b = ConstVal::Bool(bits == 1);
-            assert_eq!(b, ctfe, "miri evaluated to {:?}, but ctfe yielded {:?}", b, ctfe);
-        },
-        TyChar => {
-            let bits = get_prim(ecx, miri_val);
-            if let Some(cm) = ::std::char::from_u32(bits as u32) {
-                assert_eq!(
-                    ConstVal::Char(cm), ctfe,
-                    "miri evaluated to {:?}, but expected {:?}", cm, ctfe,
-                );
-            } else {
-                bug!("miri evaluated to {}, but expected a char {:?}", bits, ctfe);
-            }
-        },
-        TyStr => {
-            let value = ecx.follow_by_ref_value(miri_val.value, miri_val.ty);
-            if let Ok(Value::ByValPair(PrimVal::Ptr(ptr), PrimVal::Bytes(len))) = value {
-                let bytes = ecx
-                    .memory
-                    .read_bytes(ptr.into(), len as u64)
-                    .expect("bad miri memory for str");
-                if let Ok(s) = ::std::str::from_utf8(bytes) {
-                    if let ConstVal::Str(s2) = ctfe {
-                        assert_eq!(s, s2, "miri produced {:?}, but expected {:?}", s, s2);
-                    } else {
-                        bug!("miri produced {:?}, but expected {:?}", s, ctfe);
-                    }
-                } else {
-                    bug!(
-                        "miri failed to produce valid utf8 {:?}, while ctfe produced {:?}",
-                        bytes,
-                        ctfe,
-                    );
-                }
-            } else {
-                bug!("miri evaluated to {:?}, but expected a str {:?}", value, ctfe);
-            }
-        },
-        TyArray(elem_ty, n) => {
-            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)
-                }).collect(),
-                ConstVal::Aggregate(Array(v)) => {
-                    v.iter().map(|c| (c.val, c.ty)).collect()
-                },
-                ConstVal::Aggregate(Repeat(v, n)) => {
-                    vec![(v.val, v.ty); n as usize]
-                },
-                _ => bug!("miri produced {:?}, but ctfe yielded {:?}", miri_ty, ctfe),
-            };
-            let layout = ecx.layout_of(miri_ty).unwrap();
-            for (i, elem) in vec.into_iter().enumerate() {
-                assert!((i as u64) < n);
-                let (field_place, _) =
-                    ecx.place_field(miri_place, Field::new(i), layout).unwrap();
-                check_ctfe_against_miri(ecx, field_place, elem_ty, elem.0);
-            }
-        },
-        TyTuple(..) => {
-            let vec = match ctfe {
-                ConstVal::Aggregate(Tuple(v)) => v,
-                _ => bug!("miri produced {:?}, but ctfe yielded {:?}", miri_ty, ctfe),
-            };
-            let layout = ecx.layout_of(miri_ty).unwrap();
-            for (i, elem) in vec.into_iter().enumerate() {
-                let (field_place, _) =
-                    ecx.place_field(miri_place, Field::new(i), layout).unwrap();
-                check_ctfe_against_miri(ecx, field_place, elem.ty, elem.val);
-            }
-        },
-        TyAdt(def, _) => {
-            let mut miri_place = miri_place;
-            let struct_variant = if def.is_enum() {
-                let discr = ecx.read_discriminant_value(miri_place, miri_ty).unwrap();
-                let variant = def.discriminants(ecx.tcx).position(|variant_discr| {
-                    variant_discr.to_u128_unchecked() == discr
-                }).expect("miri produced invalid enum discriminant");
-                miri_place = ecx.place_downcast(miri_place, variant).unwrap();
-                &def.variants[variant]
-            } else {
-                def.non_enum_variant()
-            };
-            let vec = match ctfe {
-                ConstVal::Aggregate(Struct(v)) => v,
-                ConstVal::Variant(did) => {
-                    assert_eq!(struct_variant.fields.len(), 0);
-                    assert_eq!(did, struct_variant.did);
-                    return;
-                },
-                ctfe => bug!("miri produced {:?}, but ctfe yielded {:?}", miri_ty, ctfe),
-            };
-            let layout = ecx.layout_of(miri_ty).unwrap();
-            for &(name, elem) in vec.into_iter() {
-                let field = struct_variant.fields.iter().position(|f| f.name == name).unwrap();
-                let (field_place, _) =
-                    ecx.place_field(miri_place, Field::new(field), layout).unwrap();
-                check_ctfe_against_miri(ecx, field_place, elem.ty, elem.val);
-            }
-        },
-        TySlice(_) => bug!("miri produced a slice?"),
-        // not supported by ctfe
-        TyRawPtr(_) |
-        TyRef(..) => {}
-        TyDynamic(..) => bug!("miri produced a trait object"),
-        TyClosure(..) => bug!("miri produced a closure"),
-        TyGenerator(..) => bug!("miri produced a generator"),
-        TyGeneratorWitness(..) => bug!("miri produced a generator witness"),
-        TyNever => bug!("miri produced a value of the never type"),
-        TyProjection(_) => bug!("miri produced a projection"),
-        TyAnon(..) => bug!("miri produced an impl Trait type"),
-        TyParam(_) => bug!("miri produced an unmonomorphized type"),
-        TyInfer(_) => bug!("miri produced an uninferred type"),
-        TyError => bug!("miri produced a type error"),
-        TyForeign(_) => bug!("miri produced an extern type"),
-        // should be fine
-        TyFnDef(..) => {}
-        TyFnPtr(_) => {
-            let value = ecx.value_to_primval(miri_val);
-            let ptr = match value {
-                Ok(PrimVal::Ptr(ptr)) => ptr,
-                value => bug!("expected fn ptr, got {:?}", value),
-            };
-            let inst = ecx.memory.get_fn(ptr).unwrap();
-            match ctfe {
-                ConstVal::Function(did, substs) => {
-                    let ctfe = ty::Instance::resolve(
-                        ecx.tcx,
-                        ecx.param_env,
-                        did,
-                        substs,
-                    ).unwrap();
-                    assert_eq!(inst, ctfe, "expected fn ptr {:?}, but got {:?}", ctfe, inst);
-                },
-                _ => bug!("ctfe produced {:?}, but miri produced function {:?}", ctfe, inst),
-            }
-        },
-    }
-}
-
-fn get_prim<'a, 'tcx>(
-    ecx: &mut EvalContext<'a, 'tcx, CompileTimeEvaluator>,
-    val: ValTy<'tcx>,
-) -> u128 {
-    let res = ecx.value_to_primval(val).and_then(|prim| prim.to_bytes());
-    unwrap_miri(ecx, res)
-}
-
-fn unwrap_miri<'a, 'tcx, T>(
-    ecx: &EvalContext<'a, 'tcx, CompileTimeEvaluator>,
-    res: Result<T, EvalError<'tcx>>,
-) -> T {
-    match res {
-        Ok(val) => val,
-        Err(mut err) => {
-            ecx.report(&mut err);
-            ecx.tcx.sess.abort_if_errors();
-            bug!("{:#?}", err);
+        Err(err) => {
+            Err(ConstEvalErr { span: body.value.span, kind: err.into() })
         }
     }
 }
index f37fb3072b5841c64abe3541dd5fcdbf6edd140f..63939f7e03817e16f059ed893693e21201bc6d92 100644 (file)
@@ -241,39 +241,16 @@ pub fn str_to_value(&mut self, s: &str) -> EvalResult<'tcx, Value> {
     }
 
     pub(super) fn const_to_value(&mut self, const_val: &ConstVal<'tcx>, ty: Ty<'tcx>) -> EvalResult<'tcx, Value> {
-        use rustc::middle::const_val::ConstVal;
-
-        let primval = match *const_val {
-            ConstVal::Integral(const_int) => PrimVal::Bytes(const_int.to_u128_unchecked()),
-
-            ConstVal::Float(val) => PrimVal::Bytes(val.bits),
-
-            ConstVal::Bool(b) => PrimVal::from_bool(b),
-            ConstVal::Char(c) => PrimVal::from_char(c),
-
-            ConstVal::Str(ref s) => return self.str_to_value(s),
-
-            ConstVal::ByteStr(ref bs) => {
-                let ptr = self.memory.allocate_cached(bs.data);
-                PrimVal::Ptr(ptr)
-            }
-
+        match *const_val {
             ConstVal::Unevaluated(def_id, substs) => {
                 let instance = self.resolve(def_id, substs)?;
-                return Ok(self.read_global_as_value(GlobalId {
+                Ok(self.read_global_as_value(GlobalId {
                     instance,
                     promoted: None,
-                }, self.layout_of(ty)?));
+                }, self.layout_of(ty)?))
             }
-
-            ConstVal::Aggregate(..) |
-            ConstVal::Variant(_) => bug!("should not have aggregate or variant constants in MIR"),
-            // function items are zero sized and thus have no readable value
-            ConstVal::Function(..) => PrimVal::Undef,
-            ConstVal::Value(val) => return Ok(val),
-        };
-
-        Ok(Value::ByVal(primval))
+            ConstVal::Value(val) => Ok(val),
+        }
     }
 
     pub(super) fn resolve(&self, def_id: DefId, substs: &'tcx Substs<'tcx>) -> EvalResult<'tcx, ty::Instance<'tcx>> {
index a6ebdd45968fcd0913116ba57f26870be0c760fb..ba894a1728a9b1624282a63dec941a3329efe647 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, const_val_field, const_discr};
+pub use self::const_eval::{eval_body_as_integer, eval_body, CompileTimeEvaluator, const_eval_provider, const_val_field, const_discr, check_body};
 
 pub use self::machine::Machine;
index c5e4eeab86709f69bd680bc13a14cf1f6c4355b4..4a2b4547cb051bd48810dcf38e82c1626629e503 100644 (file)
@@ -118,10 +118,14 @@ pub fn try_read_place(
     pub fn read_field(
         &self,
         base: Value,
+        variant: Option<usize>,
         field: mir::Field,
         base_ty: Ty<'tcx>,
     ) -> EvalResult<'tcx, Option<(Value, Ty<'tcx>)>> {
-        let base_layout = self.layout_of(base_ty)?;
+        let mut base_layout = self.layout_of(base_ty)?;
+        if let Some(variant_index) = variant {
+            base_layout = base_layout.for_variant(self, variant_index);
+        }
         let field_index = field.index();
         let field = base_layout.field(self, field_index)?;
         let offset = base_layout.fields.offset(field_index);
@@ -149,7 +153,7 @@ fn try_read_place_projection(
         };
         let base_ty = self.place_ty(&proj.base);
         match proj.elem {
-            Field(field, _) => Ok(self.read_field(base, field, base_ty)?.map(|(f, _)| f)),
+            Field(field, _) => Ok(self.read_field(base, None, field, base_ty)?.map(|(f, _)| f)),
             // The NullablePointer cases should work fine, need to take care for normal enums
             Downcast(..) |
             Subslice { .. } |
index 11dded1d3f075b57059359ca7cd31deae8901bff..ae790971ec8632482f59dac2fc31d93981faa261 100644 (file)
@@ -16,7 +16,7 @@
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::subst::{Kind, Subst, Substs};
 use rustc::ty::maps::Providers;
-use rustc_const_math::{ConstInt, ConstUsize};
+use rustc_const_math::ConstUsize;
 use rustc::mir::interpret::{Value, PrimVal};
 
 use rustc_data_structures::indexed_vec::{IndexVec, Idx};
@@ -444,12 +444,8 @@ fn make_clone_call(
             ty: func_ty,
             literal: Literal::Value {
                 value: tcx.mk_const(ty::Const {
-                    val: if tcx.sess.opts.debugging_opts.miri {
-                        // ZST function type
-                        ConstVal::Value(Value::ByVal(PrimVal::Undef))
-                    } else {
-                        ConstVal::Function(self.def_id, substs)
-                    },
+                    // ZST function type
+                    val: ConstVal::Value(Value::ByVal(PrimVal::Undef)),
                     ty: func_ty
                 }),
             },
@@ -512,14 +508,12 @@ fn make_usize(&self, value: u64) -> Box<Constant<'tcx>> {
             ty: self.tcx.types.usize,
             literal: Literal::Value {
                 value: self.tcx.mk_const(ty::Const {
-                    val: if self.tcx.sess.opts.debugging_opts.miri {
-                        ConstVal::Value(Value::ByVal(PrimVal::Bytes(value.into())))
-                    } else {
+                    val: {
                         let value = ConstUsize::new(
                             value,
                             self.tcx.sess.target.usize_ty,
-                        ).unwrap();
-                        ConstVal::Integral(ConstInt::Usize(value))
+                        ).unwrap().as_u64();
+                        ConstVal::Value(Value::ByVal(PrimVal::Bytes(value.into())))
                     },
                     ty: self.tcx.types.usize,
                 })
@@ -752,12 +746,8 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 ty,
                 literal: Literal::Value {
                     value: tcx.mk_const(ty::Const {
-                        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))
-                        },
+                        // ZST function type
+                        val: ConstVal::Value(Value::ByVal(PrimVal::Undef)),
                         ty
                     }),
                 },
index 9eca343cb5edceb6fe45d11a0752fdb7d2f13252..2e8dd623d744d4a406efb540b09bf0e4accabba7 100644 (file)
@@ -19,6 +19,7 @@
 use rustc::ty::{self, TyCtxt};
 use rustc::mir::*;
 use rustc::middle::const_val::ConstVal;
+use rustc::mir::interpret::{Value, PrimVal};
 use rustc::util::nodemap::FxHashMap;
 use rustc_data_structures::indexed_set::IdxSetBuf;
 use rustc_data_structures::indexed_vec::Idx;
@@ -541,7 +542,7 @@ fn constant_bool(&self, span: Span, val: bool) -> Rvalue<'tcx> {
             ty: self.tcx.types.bool,
             literal: Literal::Value {
                 value: self.tcx.mk_const(ty::Const {
-                    val: ConstVal::Bool(val),
+                    val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(val as u128))),
                     ty: self.tcx.types.bool
                 })
             }
index ec3edb1e0680e58414abe86d4ccd1773c4eda013..0ff735694338808f6af2b7007c2589426432b53e 100644 (file)
@@ -68,7 +68,6 @@
 use rustc::ty::subst::Substs;
 use util::dump_mir;
 use util::liveness::{self, LivenessMode};
-use rustc_const_math::ConstInt;
 use rustc_data_structures::indexed_vec::Idx;
 use rustc_data_structures::indexed_set::IdxSetBuf;
 use std::collections::HashMap;
@@ -182,11 +181,7 @@ 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: if self.tcx.sess.opts.debugging_opts.miri {
-                        ConstVal::Value(Value::ByVal(PrimVal::Bytes(state_disc.into())))
-                    } else {
-                        ConstVal::Integral(ConstInt::U32(state_disc))
-                    },
+                    val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(state_disc.into()))),
                     ty: self.tcx.types.u32
                 }),
             },
@@ -703,7 +698,7 @@ fn insert_panic_block<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             ty: tcx.types.bool,
             literal: Literal::Value {
                 value: tcx.mk_const(ty::Const {
-                    val: ConstVal::Bool(false),
+                    val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(0))),
                     ty: tcx.types.bool
                 }),
             },
index ca7f573b58a4775840c065c55006ed5d7eeb0521..e39f5412355bf0dbccf5c6806923478405374a22 100644 (file)
@@ -13,6 +13,7 @@
 use rustc::ty::{self, TyCtxt};
 use rustc::middle::const_val::ConstVal;
 use rustc::mir::*;
+use rustc::mir::interpret::{Value, PrimVal};
 use transform::{MirPass, MirSource};
 
 use std::borrow::Cow;
@@ -56,9 +57,12 @@ fn run_pass<'a, 'tcx>(&self,
                 },
                 TerminatorKind::Assert { target, cond: Operand::Constant(box Constant {
                     literal: Literal::Value {
-                        value: &ty::Const { val: ConstVal::Bool(cond), .. }
+                        value: &ty::Const {
+                            val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(cond))),
+                        .. }
                     }, ..
-                }), expected, .. } if cond == expected => {
+                }), expected, .. } if (cond == 1) == expected => {
+                    assert!(cond <= 1);
                     TerminatorKind::Goto { target: target }
                 },
                 TerminatorKind::FalseEdges { real_target, .. } => {
index 77ef2c20117f1ecb215f2fba658a292e4af42df5..2ad1580f75dcd59c747c3becc1083b80afd45b2f 100644 (file)
@@ -950,11 +950,7 @@ fn constant_usize(&self, val: u16) -> Operand<'tcx> {
             ty: self.tcx().types.usize,
             literal: Literal::Value {
                 value: self.tcx().mk_const(ty::Const {
-                    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))
-                    },
+                    val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(val.into()))),
                     ty: self.tcx().types.usize
                 })
             }
index 420e8c4aad2c2401d07e5a7929fac6d794cead1f..013bc07d8e9a78308560b6a1bd389e10761cdfa6 100644 (file)
 // by borrowck::gather_loans
 
 use rustc::ty::cast::CastKind;
-use rustc_mir::const_eval::ConstContext;
-use rustc::middle::const_val::ConstEvalErr;
-use rustc::middle::const_val::ErrKind::{IndexOpFeatureGated, UnimplementedConstVal, MiscCatchAll};
-use rustc::middle::const_val::ErrKind::{ErroneousReferencedConstant, MiscBinaryOp, NonConstPath};
-use rustc::middle::const_val::ErrKind::{TypeckError, Math, LayoutError};
-use rustc_const_math::{ConstMathErr, Op};
 use rustc::hir::def::{Def, CtorKind};
 use rustc::hir::def_id::DefId;
 use rustc::hir::map::blocks::FnLikeNode;
 use rustc::ty::maps::{queries, Providers};
 use rustc::ty::subst::Substs;
 use rustc::traits::Reveal;
-use rustc::util::common::ErrorReported;
 use rustc::util::nodemap::{ItemLocalSet, NodeSet};
-use rustc::lint::builtin::CONST_ERR;
-use rustc::hir::{self, PatKind, RangeEnd};
+use rustc::hir;
 use rustc_data_structures::sync::Lrc;
 use syntax::ast;
 use syntax_pos::{Span, DUMMY_SP};
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
 
-use std::cmp::Ordering;
-
 pub fn provide(providers: &mut Providers) {
     *providers = Providers {
         rvalue_promotable_map,
@@ -124,32 +114,6 @@ struct CheckCrateVisitor<'a, 'tcx: 'a> {
 }
 
 impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> {
-    fn const_cx(&self) -> ConstContext<'a, 'gcx> {
-        ConstContext::new(self.tcx, self.param_env.and(self.identity_substs), self.tables)
-    }
-
-    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(_) => {}
-                IndexOpFeatureGated => {}
-                ErroneousReferencedConstant(_) => {}
-                TypeckError => {}
-                MiscCatchAll => {}
-                _ => {
-                    self.tcx.lint_node(CONST_ERR,
-                                       expr.id,
-                                       expr.span,
-                                       &format!("constant evaluation error: {}",
-                                                err.description().into_oneline()));
-                }
-            }
-        }
-    }
-
     // Returns true iff all the values of the type are promotable.
     fn type_has_only_promotable_values(&mut self, ty: Ty<'gcx>) -> bool {
         ty.is_freeze(self.tcx, self.param_env, DUMMY_SP) &&
@@ -199,9 +163,6 @@ fn visit_nested_body(&mut self, body_id: hir::BodyId) {
         self.identity_substs = Substs::identity_for_item(self.tcx, item_def_id);
 
         let body = self.tcx.hir.body(body_id);
-        if !self.in_fn {
-            self.check_const_eval(&body.value);
-        }
 
         let tcx = self.tcx;
         let param_env = self.param_env;
@@ -217,54 +178,6 @@ fn visit_nested_body(&mut self, body_id: hir::BodyId) {
         self.identity_substs = outer_identity_substs;
     }
 
-    fn visit_pat(&mut self, p: &'tcx hir::Pat) {
-        match p.node {
-            PatKind::Lit(ref lit) => {
-                self.check_const_eval(lit);
-            }
-            PatKind::Range(ref start, ref end, RangeEnd::Excluded) => {
-                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(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,
-                            E0030,
-                            "lower range bound must be less than or equal to upper"
-                        );
-                        err.span_label(start.span, "lower bound larger than upper bound");
-                        if self.tcx.sess.teach(&err.get_code().unwrap()) {
-                            err.note("When matching against a range, the compiler verifies that \
-                                      the range is non-empty. Range patterns include both \
-                                      end-points, so this is equivalent to requiring the start of \
-                                      the range to be less than or equal to the end of the range.");
-                        }
-                        err.emit();
-                    }
-                    Ok(None) => bug!("ranges must be char or int"),
-                    Err(ErrorReported) => {}
-                }
-            }
-            _ => {}
-        }
-        intravisit::walk_pat(self, p);
-    }
-
     fn visit_stmt(&mut self, stmt: &'tcx hir::Stmt) {
         match stmt.node {
             hir::StmtDecl(ref decl, _) => {
@@ -313,30 +226,6 @@ fn visit_expr(&mut self, ex: &'tcx hir::Expr) {
             self.promotable = false;
         }
 
-        if self.in_fn && self.promotable && !self.tcx.sess.opts.debugging_opts.miri {
-            match self.const_cx().eval(ex) {
-                Ok(_) => {}
-                Err(ConstEvalErr { kind: UnimplementedConstVal(_), .. }) |
-                Err(ConstEvalErr { kind: MiscCatchAll, .. }) |
-                Err(ConstEvalErr { kind: MiscBinaryOp, .. }) |
-                Err(ConstEvalErr { kind: NonConstPath, .. }) |
-                Err(ConstEvalErr { kind: ErroneousReferencedConstant(_), .. }) |
-                Err(ConstEvalErr { kind: Math(ConstMathErr::Overflow(Op::Shr)), .. }) |
-                Err(ConstEvalErr { kind: Math(ConstMathErr::Overflow(Op::Shl)), .. }) |
-                Err(ConstEvalErr { kind: IndexOpFeatureGated, .. }) => {}
-                Err(ConstEvalErr { kind: TypeckError, .. }) => {}
-                Err(ConstEvalErr {
-                    kind: LayoutError(ty::layout::LayoutError::Unknown(_)), ..
-                }) => {}
-                Err(msg) => {
-                    self.tcx.lint_node(CONST_ERR,
-                                       ex.id,
-                                       msg.span,
-                                       &msg.description().into_oneline().into_owned());
-                }
-            }
-        }
-
         if self.promotable {
             self.result.insert(ex.hir_id.local_id);
         }
index 184fab778c60191d13dea1b8c3ba404188cde694..7a54fc72d53cc68a54aa3bd28c012b4df49a759b 100644 (file)
 ```
 "##,
 */
-E0030: r##"
-When matching against a range, the compiler verifies that the range is
-non-empty.  Range patterns include both end-points, so this is equivalent to
-requiring the start of the range to be less than or equal to the end of the
-range.
-
-For example:
-
-```compile_fail
-match 5u32 {
-    // This range is ok, albeit pointless.
-    1 ... 1 => {}
-    // This range is empty, and the compiler can tell.
-    1000 ... 5 => {}
-}
-```
-"##,
 
 E0130: r##"
 You declared a pattern as an argument in a foreign function declaration.
@@ -228,24 +211,6 @@ fn foo() {}
 "##,
 
 
-E0579: r##"
-When matching against an exclusive range, the compiler verifies that the range
-is non-empty. Exclusive range patterns include the start point but not the end
-point, so this is equivalent to requiring the start of the range to be less
-than the end of the range.
-
-For example:
-
-```compile_fail
-match 5u32 {
-    // This range is ok, albeit pointless.
-    1 .. 2 => {}
-    // This range is empty, and the compiler can tell.
-    5 .. 5 => {}
-}
-```
-"##,
-
 E0590: r##"
 `break` or `continue` must include a label when used in the condition of a
 `while` loop.
index c88e39d7824c7213c1c2feee011e8fbf5adef56a..da10fcffb4c64509fb468c762d8b203fe8d5b58e 100644 (file)
@@ -119,7 +119,6 @@ fn visit_terminator_kind(&mut self,
                 }),
                 ref args, ..
             } => 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,
index 5bd5f19a57c63fbe671f1d7e0525fadffe1024e0..66173cfef920393f6575d1854fc0f4bc6b17a34f 100644 (file)
@@ -10,7 +10,6 @@
 
 use llvm::{self, ValueRef};
 use rustc::middle::const_val::{ConstEvalErr, ConstVal, ErrKind};
-use rustc_const_math::ConstInt::*;
 use rustc_const_math::{ConstInt, ConstMathErr, MAX_F32_PLUS_HALF_ULP};
 use rustc::hir::def_id::DefId;
 use rustc::infer::TransNormalize;
@@ -64,25 +63,6 @@ pub fn new(llval: ValueRef, ty: Ty<'tcx>) -> Const<'tcx> {
         }
     }
 
-    pub fn from_constint(cx: &CodegenCx<'a, 'tcx>, ci: &ConstInt) -> Const<'tcx> {
-        let tcx = cx.tcx;
-        let (llval, ty) = match *ci {
-            I8(v) => (C_int(Type::i8(cx), v as i64), tcx.types.i8),
-            I16(v) => (C_int(Type::i16(cx), v as i64), tcx.types.i16),
-            I32(v) => (C_int(Type::i32(cx), v as i64), tcx.types.i32),
-            I64(v) => (C_int(Type::i64(cx), v as i64), tcx.types.i64),
-            I128(v) => (C_uint_big(Type::i128(cx), v as u128), tcx.types.i128),
-            Isize(v) => (C_int(Type::isize(cx), v.as_i64()), tcx.types.isize),
-            U8(v) => (C_uint(Type::i8(cx), v as u64), tcx.types.u8),
-            U16(v) => (C_uint(Type::i16(cx), v as u64), tcx.types.u16),
-            U32(v) => (C_uint(Type::i32(cx), v as u64), tcx.types.u32),
-            U64(v) => (C_uint(Type::i64(cx), v), tcx.types.u64),
-            U128(v) => (C_uint_big(Type::i128(cx), v), tcx.types.u128),
-            Usize(v) => (C_uint(Type::isize(cx), v.as_u64()), tcx.types.usize),
-        };
-        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) |
@@ -124,26 +104,7 @@ pub fn from_constval(cx: &CodegenCx<'a, '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 {
-                    ast::FloatTy::F32 => C_u32(cx, v.bits as u32),
-                    ast::FloatTy::F64 => C_u64(cx, v.bits as u64)
-                };
-                consts::bitcast(bits, llty)
-            }
-            ConstVal::Bool(v) => C_bool(cx, v),
-            ConstVal::Integral(ref i) => return Const::from_constint(cx, i),
-            ConstVal::Str(ref v) => C_str_slice(cx, v.clone()),
-            ConstVal::ByteStr(v) => {
-                consts::addr_of(cx, C_bytes(cx, v.data), cx.align_of(ty), "byte_str")
-            }
-            ConstVal::Char(c) => C_uint(Type::char(cx), c as u64),
-            ConstVal::Function(..) => C_undef(llty),
-            ConstVal::Variant(_) |
-            ConstVal::Aggregate(..) |
-            ConstVal::Unevaluated(..) => {
-                bug!("MIR must not use `{:?}` (aggregates are expanded to MIR rvalues)", cv)
-            }
+            ConstVal::Unevaluated(..) => unimplemented!("const val `{:?}`", cv),
             ConstVal::Value(MiriValue::ByRef(..)) => unimplemented!("{:#?}:{}", cv, ty),
             ConstVal::Value(MiriValue::ByValPair(PrimVal::Ptr(ptr), PrimVal::Bytes(len))) => {
                 match ty.sty {
@@ -157,7 +118,7 @@ pub fn from_constval(cx: &CodegenCx<'a, 'tcx>,
                     .tcx()
                     .interpret_interner
                     .borrow()
-                    .get_alloc(ptr.alloc_id.0)
+                    .get_alloc(ptr.alloc_id)
                     .expect("miri alloc not found");
                 assert_eq!(len as usize as u128, len);
                 let slice = &alloc.bytes[(ptr.offset as usize)..][..(len as usize)];
@@ -174,7 +135,7 @@ pub fn from_constval(cx: &CodegenCx<'a, 'tcx>,
                     .tcx()
                     .interpret_interner
                     .borrow()
-                    .get_alloc(ptr.alloc_id.0)
+                    .get_alloc(ptr.alloc_id)
                     .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")
index 5ed35e8203cecacc03891325634a7cbd028b4aaa..595ae463ab0f1d4bb547a728a5cd3b72a993b7cb 100644 (file)
@@ -533,7 +533,6 @@ 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))),
                     ..
index e3548d740717f6142fcb99794681820069d85520..74121e3a420f9f74c941a812c548eec20ca36cd5 100644 (file)
@@ -12,6 +12,5 @@ fn main() {
     // FIXME(#31407) this error should go away, but in the meantime we test that it
     // is accompanied by a somewhat useful error message.
     let _: f64 = 1234567890123456789012345678901234567890e-340;
-    //~^ ERROR constant evaluation error
-    //~| unimplemented constant expression: could not evaluate float literal
+    //~^ ERROR could not evaluate float literal (see issue #31407)
 }
index aa0750230649da8ea1f8a2d8e9e42ba5da066787..f01fd1fd8f1442571c9a7cfa6f9005f647b335a2 100644 (file)
@@ -22,7 +22,9 @@ fn dim() -> usize {
 
 fn main() {
     let array: [usize; Dim3::dim()]
-    //~^ ERROR calls in constants are limited to constant functions
+    //~^ ERROR E0015
+    //~| ERROR E0080
         = [0; Dim3::dim()];
-        //~^ ERROR calls in constants are limited to constant functions
+        //~^ ERROR E0015
+        //~| ERROR E0080
 }
index 191b867e7a8b5cbfa4fee4ebeaf516e8f4af093f..823ece2bdca01d38b5c0279360f664c57851b826 100644 (file)
 fn main() {
     let x = 42.0;
     match x {
-        5.0 => {}, //~ ERROR floating-point literals cannot be used
+        5.0 => {}, //~ ERROR floating-point cannot be used
                    //~| WARNING hard error
-        5.0f32 => {}, //~ ERROR floating-point literals cannot be used
+        5.0f32 => {}, //~ ERROR floating-point cannot be used
                       //~| WARNING hard error
-        -5.0 => {}, //~ ERROR floating-point literals cannot be used
+        -5.0 => {}, //~ ERROR floating-point cannot be used
                     //~| WARNING hard error
-        1.0 .. 33.0 => {}, //~ ERROR floating-point literals cannot be used
+        1.0 .. 33.0 => {}, //~ ERROR floating-point cannot be used
                            //~| WARNING hard error
-                           //~| ERROR floating-point literals cannot be used
+                           //~| ERROR floating-point cannot be used
                            //~| WARNING hard error
-        39.0 ... 70.0 => {}, //~ ERROR floating-point literals cannot be used
+        39.0 ... 70.0 => {}, //~ ERROR floating-point cannot be used
                              //~| WARNING hard error
-                             //~| ERROR floating-point literals cannot be used
+                             //~| ERROR floating-point cannot be used
                              //~| WARNING hard error
         _ => {},
     };
     let y = 5.0;
     // Same for tuples
     match (x, 5) {
-        (3.14, 1) => {}, //~ ERROR floating-point literals cannot be used
+        (3.14, 1) => {}, //~ ERROR floating-point cannot be used
                          //~| WARNING hard error
         _ => {},
     }
     // Or structs
     struct Foo { x: f32 };
     match (Foo { x }) {
-        Foo { x: 2.0 } => {}, //~ ERROR floating-point literals cannot be used
+        Foo { x: 2.0 } => {}, //~ ERROR floating-point cannot be used
                               //~| WARNING hard error
         _ => {},
     }
index 3e51550d1fa07bc336bcb1da6f19545643e0674b..e94d1ff779367e20dcf3c30b0b4e04d82f1b24ad 100644 (file)
@@ -53,7 +53,7 @@ fn main() {
       let n = n << 8; //~ ERROR: bitshift exceeds the type's number of bits
 
       let n = 1u8 << -8; //~ ERROR: bitshift exceeds the type's number of bits
-      //~^ WARN: attempt to shift by a negative amount
+
 
       let n = 1u8 << (4+3);
       let n = 1u8 << (4+4); //~ ERROR: bitshift exceeds the type's number of bits
index 5593499758346d37c7cd001c55e95cd0579e2716..f7cf8a68d568446119a63c5b9d74cd05794589d7 100644 (file)
@@ -17,7 +17,6 @@
 #[rustc_error]
 fn main() { //~ ERROR: compilation successful
     let x2: i8 = --128; //~ warn: literal out of range for i8
-    //~^ warn: attempt to negate with overflow
 
     let x = -3.40282357e+38_f32; //~ warn: literal out of range for f32
     let x =  3.40282357e+38_f32; //~ warn: literal out of range for f32
index 679be9ce219fe548a9954e9beacf51d58fda3984..fd888b659f14262813460c2185f6ae246bd03b71 100644 (file)
@@ -28,7 +28,8 @@ fn main() {
     let x = 0.0;
     match x {
         f32::INFINITY => { }
-        //~^ ERROR floating point constants cannot be used in patterns
+        //~^ WARNING floating-point cannot be used in patterns
+        //~| WARNING will become a hard error in a future release
         _ => { }
     }
 }
index 720e15991c05988c4284dcb13a1c74be159f5b6b..dc220bd1cc94fbfa81432109dbf7e16e32493fe8 100644 (file)
@@ -16,7 +16,6 @@
 static B: u32 = A;
 //~^ ERROR thread-local statics cannot be accessed at compile-time
 //~| ERROR cannot refer to other statics by value
-//~| WARN non-constant path in constant expression
 
 static C: &u32 = &A;
 //~^ ERROR thread-local statics cannot be accessed at compile-time
@@ -24,7 +23,6 @@
 const D: u32 = A;
 //~^ ERROR thread-local statics cannot be accessed at compile-time
 //~| ERROR cannot refer to statics by value
-//~| WARN non-constant path in constant expression
 
 const E: &u32 = &A;
 //~^ ERROR thread-local statics cannot be accessed at compile-time