]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #50526 - moxian:just-fix, r=alexcrichton
authorbors <bors@rust-lang.org>
Fri, 29 Jun 2018 09:42:40 +0000 (09:42 +0000)
committerbors <bors@rust-lang.org>
Fri, 29 Jun 2018 09:42:40 +0000 (09:42 +0000)
Add a fallback for stacktrace printing for older Windows versions.

Some time ago we switched stack inspection functions of dbghelp.dll to their newer alternatives that also capture inlined context.
Unfortunately, said new alternatives are not present in older dbghelp.dll versions.
In particular Windows 7 at the time of writing has dbghelp.dll version 6.1.7601 from 2010, that lacks StackWalkEx and friends.

Tested on my Windows 7 - both msvc and gnu versions produce a readable stacktrace.

Fixes #50138

74 files changed:
RELEASES.md
src/liballoc/arc.rs
src/libcore/slice/mod.rs
src/librustc/dep_graph/dep_node.rs
src/librustc/ich/impls_ty.rs
src/librustc/lib.rs
src/librustc/middle/const_val.rs [deleted file]
src/librustc/mir/interpret/error.rs
src/librustc/mir/interpret/mod.rs
src/librustc/mir/interpret/value.rs
src/librustc/mir/mod.rs
src/librustc/traits/fulfill.rs
src/librustc/traits/mod.rs
src/librustc/traits/project.rs
src/librustc/traits/query/normalize.rs
src/librustc/traits/structural_impls.rs
src/librustc/ty/flags.rs
src/librustc/ty/fold.rs
src/librustc/ty/mod.rs
src/librustc/ty/query/config.rs
src/librustc/ty/query/keys.rs
src/librustc/ty/query/mod.rs
src/librustc/ty/relate.rs
src/librustc/ty/structural_impls.rs
src/librustc/ty/sty.rs
src/librustc/ty/walk.rs
src/librustc/ty/wf.rs
src/librustc/util/ppaux.rs
src/librustc_codegen_llvm/base.rs
src/librustc_codegen_llvm/mir/constant.rs
src/librustc_codegen_llvm/mir/operand.rs
src/librustc_mir/hair/pattern/_match.rs
src/librustc_mir/hair/pattern/check_match.rs
src/librustc_mir/hair/pattern/mod.rs
src/librustc_mir/interpret/const_eval.rs
src/librustc_mir/interpret/eval_context.rs
src/librustc_mir/interpret/memory.rs
src/librustc_mir/interpret/operator.rs
src/librustc_mir/monomorphize/collector.rs
src/librustc_mir/transform/const_prop.rs
src/librustc_mir/transform/qualify_consts.rs
src/librustc_target/spec/asmjs_unknown_emscripten.rs
src/librustc_typeck/check/coercion.rs
src/librustc_typeck/check/demand.rs
src/librustc_typeck/check/mod.rs
src/librustdoc/clean/mod.rs
src/librustdoc/html/static/main.js
src/libstd/thread/mod.rs
src/test/compile-fail/const-err-early.rs
src/test/compile-fail/const-err-multi.rs
src/test/compile-fail/const-err.rs
src/test/compile-fail/const-eval-overflow2.rs
src/test/compile-fail/const-eval-overflow2b.rs
src/test/compile-fail/const-eval-overflow2c.rs
src/test/rustdoc-js/macro-check.js [new file with mode: 0644]
src/test/ui/const-eval/conditional_array_execution.nll.stderr
src/test/ui/const-eval/conditional_array_execution.rs
src/test/ui/const-eval/conditional_array_execution.stderr
src/test/ui/const-eval/issue-43197.nll.stderr
src/test/ui/const-eval/issue-43197.rs
src/test/ui/const-eval/issue-43197.stderr
src/test/ui/const-eval/issue-44578.nll.stderr
src/test/ui/const-eval/issue-44578.stderr
src/test/ui/const-eval/issue-50814-2.stderr
src/test/ui/const-eval/issue-50814.stderr
src/test/ui/const-eval/pub_const_err.rs
src/test/ui/const-eval/pub_const_err.stderr
src/test/ui/const-eval/pub_const_err_bin.rs
src/test/ui/const-eval/pub_const_err_bin.stderr
src/test/ui/const-eval/shift_overflow.rs [new file with mode: 0644]
src/test/ui/const-eval/shift_overflow.stderr [new file with mode: 0644]
src/test/ui/const-len-underflow-separate-spans.rs
src/test/ui/const-len-underflow-separate-spans.stderr
src/test/ui/suggestions/str-array-assignment.stderr

index 068e9e7263e7d891cef422776d5d9c7405f0d19c..fba68ce043e261883846d6c76a5ee581bc68c064 100644 (file)
@@ -56,7 +56,6 @@ Stabilized APIs
 - [`Take::set_limit`]
 - [`hint::unreachable_unchecked`]
 - [`os::unix::process::parent_id`]
-- [`process::id`]
 - [`ptr::swap_nonoverlapping`]
 - [`slice::rsplit_mut`]
 - [`slice::rsplit`]
index 0fbd1408f644f9e3f2da1e0e709ec8509d182738..2abd9c85c5754f140beb33dcd8ac148969375215 100644 (file)
@@ -23,7 +23,7 @@
 use core::fmt;
 use core::cmp::Ordering;
 use core::intrinsics::abort;
-use core::mem::{self, align_of_val, size_of_val, uninitialized};
+use core::mem::{self, align_of_val, size_of_val};
 use core::ops::Deref;
 use core::ops::CoerceUnsized;
 use core::ptr::{self, NonNull};
@@ -43,6 +43,9 @@
 /// necessarily) at _exactly_ `MAX_REFCOUNT + 1` references.
 const MAX_REFCOUNT: usize = (isize::MAX) as usize;
 
+/// A sentinel value that is used for the pointer of `Weak::new()`.
+const WEAK_EMPTY: usize = 1;
+
 /// A thread-safe reference-counting pointer. 'Arc' stands for 'Atomically
 /// Reference Counted'.
 ///
@@ -235,6 +238,10 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Arc<U>> for Arc<T> {}
 /// [`None`]: ../../std/option/enum.Option.html#variant.None
 #[stable(feature = "arc_weak", since = "1.4.0")]
 pub struct Weak<T: ?Sized> {
+    // This is a `NonNull` to allow optimizing the size of this type in enums,
+    // but it is actually not truly "non-null". A `Weak::new()` will set this
+    // to a sentinel value, instead of needing to allocate some space in the
+    // heap.
     ptr: NonNull<ArcInner<T>>,
 }
 
@@ -1011,8 +1018,8 @@ pub fn downcast<T>(self) -> Result<Arc<T>, Self>
 }
 
 impl<T> Weak<T> {
-    /// Constructs a new `Weak<T>`, allocating memory for `T` without initializing
-    /// it. Calling [`upgrade`] on the return value always gives [`None`].
+    /// Constructs a new `Weak<T>`, without allocating any memory.
+    /// Calling [`upgrade`] on the return value always gives [`None`].
     ///
     /// [`upgrade`]: struct.Weak.html#method.upgrade
     /// [`None`]: ../../std/option/enum.Option.html#variant.None
@@ -1029,11 +1036,7 @@ impl<T> Weak<T> {
     pub fn new() -> Weak<T> {
         unsafe {
             Weak {
-                ptr: Box::into_raw_non_null(box ArcInner {
-                    strong: atomic::AtomicUsize::new(0),
-                    weak: atomic::AtomicUsize::new(1),
-                    data: uninitialized(),
-                }),
+                ptr: NonNull::new_unchecked(WEAK_EMPTY as *mut _),
             }
         }
     }
@@ -1070,7 +1073,11 @@ impl<T: ?Sized> Weak<T> {
     pub fn upgrade(&self) -> Option<Arc<T>> {
         // We use a CAS loop to increment the strong count instead of a
         // fetch_add because once the count hits 0 it must never be above 0.
-        let inner = self.inner();
+        let inner = if self.ptr.as_ptr() as *const u8 as usize == WEAK_EMPTY {
+            return None;
+        } else {
+            unsafe { self.ptr.as_ref() }
+        };
 
         // Relaxed load because any write of 0 that we can observe
         // leaves the field in a permanently zero state (so a
@@ -1092,17 +1099,15 @@ pub fn upgrade(&self) -> Option<Arc<T>> {
 
             // Relaxed is valid for the same reason it is on Arc's Clone impl
             match inner.strong.compare_exchange_weak(n, n + 1, Relaxed, Relaxed) {
-                Ok(_) => return Some(Arc { ptr: self.ptr, phantom: PhantomData }),
+                Ok(_) => return Some(Arc {
+                    // null checked above
+                    ptr: self.ptr,
+                    phantom: PhantomData,
+                }),
                 Err(old) => n = old,
             }
         }
     }
-
-    #[inline]
-    fn inner(&self) -> &ArcInner<T> {
-        // See comments above for why this is "safe"
-        unsafe { self.ptr.as_ref() }
-    }
 }
 
 #[stable(feature = "arc_weak", since = "1.4.0")]
@@ -1120,11 +1125,16 @@ impl<T: ?Sized> Clone for Weak<T> {
     /// ```
     #[inline]
     fn clone(&self) -> Weak<T> {
+        let inner = if self.ptr.as_ptr() as *const u8 as usize == WEAK_EMPTY {
+            return Weak { ptr: self.ptr };
+        } else {
+            unsafe { self.ptr.as_ref() }
+        };
         // See comments in Arc::clone() for why this is relaxed.  This can use a
         // fetch_add (ignoring the lock) because the weak count is only locked
         // where are *no other* weak pointers in existence. (So we can't be
         // running this code in that case).
-        let old_size = self.inner().weak.fetch_add(1, Relaxed);
+        let old_size = inner.weak.fetch_add(1, Relaxed);
 
         // See comments in Arc::clone() for why we do this (for mem::forget).
         if old_size > MAX_REFCOUNT {
@@ -1139,8 +1149,8 @@ fn clone(&self) -> Weak<T> {
 
 #[stable(feature = "downgraded_weak", since = "1.10.0")]
 impl<T> Default for Weak<T> {
-    /// Constructs a new `Weak<T>`, allocating memory for `T` without initializing
-    /// it. Calling [`upgrade`] on the return value always gives [`None`].
+    /// Constructs a new `Weak<T>`, without allocating memory.
+    /// Calling [`upgrade`] on the return value always gives [`None`].
     ///
     /// [`upgrade`]: struct.Weak.html#method.upgrade
     /// [`None`]: ../../std/option/enum.Option.html#variant.None
@@ -1193,7 +1203,13 @@ fn drop(&mut self) {
         // weak count can only be locked if there was precisely one weak ref,
         // meaning that drop could only subsequently run ON that remaining weak
         // ref, which can only happen after the lock is released.
-        if self.inner().weak.fetch_sub(1, Release) == 1 {
+        let inner = if self.ptr.as_ptr() as *const u8 as usize == WEAK_EMPTY {
+            return;
+        } else {
+            unsafe { self.ptr.as_ref() }
+        };
+
+        if inner.weak.fetch_sub(1, Release) == 1 {
             atomic::fence(Acquire);
             unsafe {
                 Global.dealloc(self.ptr.cast(), Layout::for_value(self.ptr.as_ref()))
index e74e527927d7bc47cff1d9ea70820a31d651ac8c..0cbdbc4ad663af99c47a7838c2c66ff44e628641 100644 (file)
@@ -1642,8 +1642,8 @@ pub fn clone_from_slice(&mut self, src: &[T]) where T: Clone {
     /// [`split_at_mut`]: #method.split_at_mut
     #[stable(feature = "copy_from_slice", since = "1.9.0")]
     pub fn copy_from_slice(&mut self, src: &[T]) where T: Copy {
-        assert!(self.len() == src.len(),
-                "destination and source slices have different lengths");
+        assert_eq!(self.len(), src.len(),
+                   "destination and source slices have different lengths");
         unsafe {
             ptr::copy_nonoverlapping(
                 src.as_ptr(), self.as_mut_ptr(), self.len());
index 33322993b1db6289be3317638f9743e252387aec..6cc61d748001a191f9bf4428080f1881dc2f285e 100644 (file)
@@ -60,7 +60,7 @@
 //! user of the `DepNode` API of having to know how to compute the expected
 //! fingerprint for a given set of node parameters.
 
-use mir::interpret::{GlobalId, ConstValue};
+use mir::interpret::GlobalId;
 use hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX};
 use hir::map::DefPathHash;
 use hir::{HirId, ItemLocalId};
@@ -75,7 +75,7 @@
     CanonicalPredicateGoal, CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpNormalizeGoal,
 };
 use ty::{TyCtxt, FnSig, Instance, InstanceDef,
-         ParamEnv, ParamEnvAnd, Predicate, PolyFnSig, PolyTraitRef, Ty};
+         ParamEnv, ParamEnvAnd, Predicate, PolyFnSig, PolyTraitRef, Ty, self};
 use ty::subst::Substs;
 
 // erase!() just makes tokens go away. It's used to specify which macro argument
@@ -632,7 +632,7 @@ pub fn fingerprint_needed_for_crate_hash(self) -> bool {
     // queries). Making them anonymous avoids hashing the result, which
     // may save a bit of time.
     [anon] EraseRegionsTy { ty: Ty<'tcx> },
-    [anon] ConstValueToAllocation { val: ConstValue<'tcx>, ty: Ty<'tcx> },
+    [anon] ConstValueToAllocation { val: &'tcx ty::Const<'tcx> },
 
     [input] Freevars(DefId),
     [input] MaybeUnusedTraitImport(DefId),
index 55bcaad1a4ea25cff5ce6e28e98cc41ecd959386..8391cc6d9ba99e286f0e4697b8042bef0d12865d 100644 (file)
@@ -364,11 +364,11 @@ fn hash_stable<W: StableHasherResult>(&self,
 });
 
 impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
-for ::middle::const_val::ConstVal<'gcx> {
+for ::mir::interpret::ConstValue<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
-        use middle::const_val::ConstVal::*;
+        use mir::interpret::ConstValue::*;
 
         mem::discriminant(self).hash_stable(hcx, hasher);
 
@@ -377,23 +377,6 @@ fn hash_stable<W: StableHasherResult>(&self,
                 def_id.hash_stable(hcx, hasher);
                 substs.hash_stable(hcx, hasher);
             }
-            Value(ref value) => {
-                value.hash_stable(hcx, hasher);
-            }
-        }
-    }
-}
-
-impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
-for ::mir::interpret::ConstValue<'gcx> {
-    fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a>,
-                                          hasher: &mut StableHasher<W>) {
-        use mir::interpret::ConstValue::*;
-
-        mem::discriminant(self).hash_stable(hcx, hasher);
-
-        match *self {
             Scalar(val) => {
                 val.hash_stable(hcx, hasher);
             }
@@ -497,40 +480,18 @@ fn hash_stable<W: StableHasherResult>(&self,
     val
 });
 
-impl_stable_hash_for!(struct ::middle::const_val::ConstEvalErr<'tcx> {
+impl_stable_hash_for!(struct ::mir::interpret::ConstEvalErr<'tcx> {
     span,
-    kind
+    stacktrace,
+    error
 });
 
-impl_stable_hash_for!(struct ::middle::const_val::FrameInfo {
+impl_stable_hash_for!(struct ::mir::interpret::FrameInfo {
     span,
     lint_root,
     location
 });
 
-impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
-for ::middle::const_val::ErrKind<'gcx> {
-    fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a>,
-                                          hasher: &mut StableHasher<W>) {
-        use middle::const_val::ErrKind::*;
-
-        mem::discriminant(self).hash_stable(hcx, hasher);
-
-        match *self {
-            TypeckError |
-            CouldNotResolve |
-            CheckMatchError => {
-                // nothing to do
-            }
-            Miri(ref err, ref trace) => {
-                err.hash_stable(hcx, hasher);
-                trace.hash_stable(hcx, hasher);
-            },
-        }
-    }
-}
-
 impl_stable_hash_for!(struct ty::ClosureSubsts<'tcx> { substs });
 impl_stable_hash_for!(struct ty::GeneratorSubsts<'tcx> { substs });
 
@@ -579,6 +540,8 @@ fn hash_stable<W: StableHasherResult>(&self,
             ReadFromReturnPointer |
             UnimplementedTraitSelection |
             TypeckError |
+            TooGeneric |
+            CheckMatchError |
             DerefFunctionPointer |
             ExecuteMemory |
             OverflowNeg |
index 102efe2bef3f750077e02e4fa67be742bdccf89d..c500800a30f9cd9717788a492b6e4f7e664b7ff7 100644 (file)
@@ -132,7 +132,6 @@ pub mod middle {
     pub mod allocator;
     pub mod borrowck;
     pub mod expr_use_visitor;
-    pub mod const_val;
     pub mod cstore;
     pub mod dataflow;
     pub mod dead;
diff --git a/src/librustc/middle/const_val.rs b/src/librustc/middle/const_val.rs
deleted file mode 100644 (file)
index 2fa77be..0000000
+++ /dev/null
@@ -1,178 +0,0 @@
-// Copyright 2012-2016 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.
-
-use hir::def_id::DefId;
-use ty;
-use ty::subst::Substs;
-use ty::query::TyCtxtAt;
-use mir::interpret::ConstValue;
-use errors::DiagnosticBuilder;
-
-use graphviz::IntoCow;
-use syntax_pos::Span;
-use syntax::ast;
-
-use std::borrow::Cow;
-use rustc_data_structures::sync::Lrc;
-
-pub type EvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, ConstEvalErr<'tcx>>;
-
-#[derive(Copy, Clone, Debug, Hash, RustcEncodable, RustcDecodable, Eq, PartialEq, Ord, PartialOrd)]
-pub enum ConstVal<'tcx> {
-    Unevaluated(DefId, &'tcx Substs<'tcx>),
-    Value(ConstValue<'tcx>),
-}
-
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
-pub struct ConstEvalErr<'tcx> {
-    pub span: Span,
-    pub kind: Lrc<ErrKind<'tcx>>,
-}
-
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
-pub enum ErrKind<'tcx> {
-
-    CouldNotResolve,
-    TypeckError,
-    CheckMatchError,
-    Miri(::mir::interpret::EvalError<'tcx>, Vec<FrameInfo>),
-}
-
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
-pub struct FrameInfo {
-    pub span: Span,
-    pub location: String,
-    pub lint_root: Option<ast::NodeId>,
-}
-
-#[derive(Clone, Debug)]
-pub enum ConstEvalErrDescription<'a, 'tcx: 'a> {
-    Simple(Cow<'a, str>),
-    Backtrace(&'a ::mir::interpret::EvalError<'tcx>, &'a [FrameInfo]),
-}
-
-impl<'a, 'tcx> ConstEvalErrDescription<'a, 'tcx> {
-    /// Return a one-line description of the error, for lints and such
-    pub fn into_oneline(self) -> Cow<'a, str> {
-        match self {
-            ConstEvalErrDescription::Simple(simple) => simple,
-            ConstEvalErrDescription::Backtrace(miri, _) => format!("{}", miri).into_cow(),
-        }
-    }
-}
-
-impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
-    pub fn description(&'a self) -> ConstEvalErrDescription<'a, 'tcx> {
-        use self::ErrKind::*;
-        use self::ConstEvalErrDescription::*;
-
-        macro_rules! simple {
-            ($msg:expr) => ({ Simple($msg.into_cow()) });
-            ($fmt:expr, $($arg:tt)+) => ({
-                Simple(format!($fmt, $($arg)+).into_cow())
-            })
-        }
-
-        match *self.kind {
-            CouldNotResolve => simple!("could not resolve"),
-            TypeckError => simple!("type-checking failed"),
-            CheckMatchError => simple!("match-checking failed"),
-            Miri(ref err, ref trace) => Backtrace(err, trace),
-        }
-    }
-
-    pub fn struct_error(&self,
-        tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
-        message: &str)
-        -> Option<DiagnosticBuilder<'tcx>>
-    {
-        self.struct_generic(tcx, message, None, true)
-    }
-
-    pub fn report_as_error(&self,
-        tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
-        message: &str
-    ) {
-        let err = self.struct_generic(tcx, message, None, true);
-        if let Some(mut err) = err {
-            err.emit();
-        }
-    }
-
-    pub fn report_as_lint(&self,
-        tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
-        message: &str,
-        lint_root: ast::NodeId,
-    ) {
-        let lint = self.struct_generic(
-            tcx,
-            message,
-            Some(lint_root),
-            false,
-        );
-        if let Some(mut lint) = lint {
-            lint.emit();
-        }
-    }
-
-    fn struct_generic(
-        &self,
-        tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
-        message: &str,
-        lint_root: Option<ast::NodeId>,
-        as_err: bool,
-    ) -> Option<DiagnosticBuilder<'tcx>> {
-        let (msg, frames): (_, &[_]) = match *self.kind {
-            ErrKind::TypeckError | ErrKind::CheckMatchError => return None,
-            ErrKind::Miri(ref miri, ref frames) => {
-                match miri.kind {
-                    ::mir::interpret::EvalErrorKind::TypeckError |
-                    ::mir::interpret::EvalErrorKind::Layout(_) => return None,
-                    ::mir::interpret::EvalErrorKind::ReferencedConstant(ref inner) => {
-                        inner.struct_generic(tcx, "referenced constant", lint_root, as_err)?.emit();
-                        (miri.to_string(), frames)
-                    },
-                    _ => (miri.to_string(), frames),
-                }
-            }
-            _ => (self.description().into_oneline().to_string(), &[]),
-        };
-        trace!("reporting const eval failure at {:?}", self.span);
-        let mut err = if as_err {
-            struct_error(tcx, message)
-        } else {
-            let node_id = frames
-                .iter()
-                .rev()
-                .filter_map(|frame| frame.lint_root)
-                .next()
-                .or(lint_root)
-                .expect("some part of a failing const eval must be local");
-            tcx.struct_span_lint_node(
-                ::rustc::lint::builtin::CONST_ERR,
-                node_id,
-                tcx.span,
-                message,
-            )
-        };
-        err.span_label(self.span, msg);
-        for FrameInfo { span, location, .. } in frames {
-            err.span_label(*span, format!("inside call to `{}`", location));
-        }
-        Some(err)
-    }
-}
-
-pub fn struct_error<'a, 'gcx, 'tcx>(
-    tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
-    msg: &str,
-) -> DiagnosticBuilder<'tcx> {
-    struct_span_err!(tcx.sess, tcx.span, E0080, "{}", msg)
-}
index bf5bae6b20c429ef15aaf6abf518c9f59fbea389..86427bb2382cb5bc7004ec8bd01b10818e289f81 100644 (file)
@@ -1,9 +1,9 @@
 use std::{fmt, env};
 
 use mir;
-use middle::const_val::ConstEvalErr;
 use ty::{FnSig, Ty, layout};
 use ty::layout::{Size, Align};
+use rustc_data_structures::sync::Lrc;
 
 use super::{
     Pointer, Lock, AccessKind
 
 use backtrace::Backtrace;
 
+use ty;
+use ty::query::TyCtxtAt;
+use errors::DiagnosticBuilder;
+
+use syntax_pos::Span;
+use syntax::ast;
+
+pub type ConstEvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, Lrc<ConstEvalErr<'tcx>>>;
+
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
+pub struct ConstEvalErr<'tcx> {
+    pub span: Span,
+    pub error: ::mir::interpret::EvalError<'tcx>,
+    pub stacktrace: Vec<FrameInfo>,
+}
+
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
+pub struct FrameInfo {
+    pub span: Span,
+    pub location: String,
+    pub lint_root: Option<ast::NodeId>,
+}
+
+impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
+    pub fn struct_error(&self,
+        tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
+        message: &str)
+        -> Option<DiagnosticBuilder<'tcx>>
+    {
+        self.struct_generic(tcx, message, None)
+    }
+
+    pub fn report_as_error(&self,
+        tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
+        message: &str
+    ) {
+        let err = self.struct_generic(tcx, message, None);
+        if let Some(mut err) = err {
+            err.emit();
+        }
+    }
+
+    pub fn report_as_lint(&self,
+        tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
+        message: &str,
+        lint_root: ast::NodeId,
+    ) {
+        let lint = self.struct_generic(
+            tcx,
+            message,
+            Some(lint_root),
+        );
+        if let Some(mut lint) = lint {
+            lint.emit();
+        }
+    }
+
+    fn struct_generic(
+        &self,
+        tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
+        message: &str,
+        lint_root: Option<ast::NodeId>,
+    ) -> Option<DiagnosticBuilder<'tcx>> {
+        match self.error.kind {
+            ::mir::interpret::EvalErrorKind::TypeckError |
+            ::mir::interpret::EvalErrorKind::TooGeneric |
+            ::mir::interpret::EvalErrorKind::CheckMatchError |
+            ::mir::interpret::EvalErrorKind::Layout(_) => return None,
+            ::mir::interpret::EvalErrorKind::ReferencedConstant(ref inner) => {
+                inner.struct_generic(tcx, "referenced constant has errors", lint_root)?.emit();
+            },
+            _ => {},
+        }
+        trace!("reporting const eval failure at {:?}", self.span);
+        let mut err = if let Some(lint_root) = lint_root {
+            let node_id = self.stacktrace
+                .iter()
+                .rev()
+                .filter_map(|frame| frame.lint_root)
+                .next()
+                .unwrap_or(lint_root);
+            tcx.struct_span_lint_node(
+                ::rustc::lint::builtin::CONST_ERR,
+                node_id,
+                tcx.span,
+                message,
+            )
+        } else {
+            struct_error(tcx, message)
+        };
+        err.span_label(self.span, self.error.to_string());
+        for FrameInfo { span, location, .. } in &self.stacktrace {
+            err.span_label(*span, format!("inside call to `{}`", location));
+        }
+        Some(err)
+    }
+}
+
+pub fn struct_error<'a, 'gcx, 'tcx>(
+    tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
+    msg: &str,
+) -> DiagnosticBuilder<'tcx> {
+    struct_span_err!(tcx.sess, tcx.span, E0080, "{}", msg)
+}
+
 #[derive(Debug, Clone, RustcEncodable, RustcDecodable)]
 pub struct EvalError<'tcx> {
     pub kind: EvalErrorKind<'tcx, u64>,
@@ -150,9 +255,12 @@ pub enum EvalErrorKind<'tcx, O> {
     UnimplementedTraitSelection,
     /// Abort in case type errors are reached
     TypeckError,
+    /// Resolution can fail if we are in a too generic context
+    TooGeneric,
+    CheckMatchError,
     /// Cannot compute this constant because it depends on another one
     /// which already produced an error
-    ReferencedConstant(ConstEvalErr<'tcx>),
+    ReferencedConstant(Lrc<ConstEvalErr<'tcx>>),
     GeneratorResumedAfterReturn,
     GeneratorResumedAfterPanic,
 }
@@ -268,6 +376,10 @@ pub fn description(&self) -> &str {
                 "there were unresolved type arguments during trait selection",
             TypeckError =>
                 "encountered constants with type errors, stopping evaluation",
+            TooGeneric =>
+                "encountered overly generic constant",
+            CheckMatchError =>
+                "match checking failed",
             ReferencedConstant(_) =>
                 "referenced constant has errors",
             Overflow(mir::BinOp::Add) => "attempt to add with overflow",
index 6bd5814799ae07d6c1847c99bfc77b11528dc55c..018c2446054be5080f2870d1804f3a32be31d171 100644 (file)
@@ -8,7 +8,10 @@ macro_rules! err {
 mod error;
 mod value;
 
-pub use self::error::{EvalError, EvalResult, EvalErrorKind, AssertMessage};
+pub use self::error::{
+    EvalError, EvalResult, EvalErrorKind, AssertMessage, ConstEvalErr, struct_error,
+    FrameInfo, ConstEvalResult,
+};
 
 pub use self::value::{Scalar, Value, ConstValue};
 
index 9e3d4e60603ec8f6173dd8b8e9a6e3db7ff26b29..24595c9328208a2a1183e1b11baad07ec9f11f17 100644 (file)
@@ -2,13 +2,19 @@
 
 use ty::layout::{Align, HasDataLayout, Size};
 use ty;
+use ty::subst::Substs;
+use hir::def_id::DefId;
 
 use super::{EvalResult, Pointer, PointerArithmetic, Allocation};
 
 /// Represents a constant value in Rust. ByVal and ScalarPair are optimizations which
 /// matches Value's optimizations for easy conversions between these two types
-#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash)]
 pub enum ConstValue<'tcx> {
+    /// Never returned from the `const_eval` query, but the HIR contains these frequently in order
+    /// to allow HIR creation to happen for everything before needing to be able to run constant
+    /// evaluation
+    Unevaluated(DefId, &'tcx Substs<'tcx>),
     /// Used only for types with layout::abi::Scalar ABI and ZSTs which use Scalar::undef()
     Scalar(Scalar),
     /// Used only for types with layout::abi::ScalarPair
@@ -30,6 +36,7 @@ pub fn from_byval_value(val: Value) -> Self {
     #[inline]
     pub fn to_byval_value(&self) -> Option<Value> {
         match *self {
+            ConstValue::Unevaluated(..) |
             ConstValue::ByRef(..) => None,
             ConstValue::ScalarPair(a, b) => Some(Value::ScalarPair(a, b)),
             ConstValue::Scalar(val) => Some(Value::Scalar(val)),
@@ -44,7 +51,8 @@ pub fn from_scalar(val: Scalar) -> Self {
     #[inline]
     pub fn to_scalar(&self) -> Option<Scalar> {
         match *self {
-            ConstValue::ByRef(..) => None,
+            ConstValue::Unevaluated(..) |
+            ConstValue::ByRef(..) |
             ConstValue::ScalarPair(..) => None,
             ConstValue::Scalar(val) => Some(val),
         }
index ee6cb398acdceecef12b853bc67886eeeb0a61ee..2198e3f6b318ef1c60f2f4af577a818eff50bd41 100644 (file)
@@ -2162,18 +2162,12 @@ fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
     }
 }
 
-/// Write a `ConstVal` in a way closer to the original source code than the `Debug` output.
+/// Write a `ConstValue` in a way closer to the original source code than the `Debug` output.
 pub fn fmt_const_val<W: Write>(fmt: &mut W, const_val: &ty::Const) -> fmt::Result {
-    use middle::const_val::ConstVal;
-    match const_val.val {
-        ConstVal::Unevaluated(..) => write!(fmt, "{:?}", const_val),
-        ConstVal::Value(val) => {
-            if let Some(value) = val.to_byval_value() {
-                print_miri_value(value, const_val.ty, fmt)
-            } else {
-                write!(fmt, "{:?}:{}", val, const_val.ty)
-            }
-        }
+    if let Some(value) = const_val.to_byval_value() {
+        print_miri_value(value, const_val.ty, fmt)
+    } else {
+        write!(fmt, "{:?}:{}", const_val.val, const_val.ty)
     }
 }
 
index b3f56d4de65340971f4372bc9f954621a4979942..e97171c481f1dd25c04fea9efdb7280be14eb2f1 100644 (file)
@@ -16,7 +16,8 @@
 use rustc_data_structures::obligation_forest::{ObligationProcessor, ProcessResult};
 use std::marker::PhantomData;
 use hir::def_id::DefId;
-use middle::const_val::{ConstEvalErr, ErrKind};
+use mir::interpret::ConstEvalErr;
+use mir::interpret::EvalErrorKind;
 
 use super::CodeAmbiguity;
 use super::CodeProjectionError;
@@ -501,8 +502,9 @@ fn process_obligation(&mut self,
                                     ProcessResult::Error(
                                         CodeSelectionError(ConstEvalFailure(ConstEvalErr {
                                             span: obligation.cause.span,
-                                            kind: ErrKind::CouldNotResolve.into(),
-                                        }))
+                                            error: EvalErrorKind::TooGeneric.into(),
+                                            stacktrace: vec![],
+                                        }.into()))
                                     )
                                 }
                             },
index c7e55fa574f94cf5ca0e28686a18535e37e2bbc6..0290f2e3b13f08e335a1319ca22b64108e9d9517 100644 (file)
@@ -22,7 +22,7 @@
 use hir::def_id::DefId;
 use infer::outlives::env::OutlivesEnvironment;
 use middle::region;
-use middle::const_val::ConstEvalErr;
+use mir::interpret::ConstEvalErr;
 use ty::subst::Substs;
 use ty::{self, AdtKind, Slice, Ty, TyCtxt, GenericParamDefKind, ToPredicate};
 use ty::error::{ExpectedFound, TypeError};
@@ -381,7 +381,7 @@ pub enum SelectionError<'tcx> {
                                 ty::PolyTraitRef<'tcx>,
                                 ty::error::TypeError<'tcx>),
     TraitNotObjectSafe(DefId),
-    ConstEvalFailure(ConstEvalErr<'tcx>),
+    ConstEvalFailure(Lrc<ConstEvalErr<'tcx>>),
     Overflow,
 }
 
index 97b15048b48f6a2db8eed5fbdfec91d8c7f5aa38..1052d029e0d648e5a0f11f2ffbf51c7bebf01f79 100644 (file)
@@ -28,7 +28,7 @@
 use hir::def_id::DefId;
 use infer::{InferCtxt, InferOk};
 use infer::type_variable::TypeVariableOrigin;
-use middle::const_val::ConstVal;
+use mir::interpret::ConstValue;
 use mir::interpret::{GlobalId};
 use rustc_data_structures::snapshot_map::{Snapshot, SnapshotMap};
 use syntax::ast::Ident;
@@ -426,7 +426,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
     }
 
     fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
-        if let ConstVal::Unevaluated(def_id, substs) = constant.val {
+        if let ConstValue::Unevaluated(def_id, substs) = constant.val {
             let tcx = self.selcx.tcx().global_tcx();
             if let Some(param_env) = self.tcx().lift_to_global(&self.param_env) {
                 if substs.needs_infer() || substs.has_skol() {
index 8d10195941e0d28e38894a149d05715c892d9ceb..a67383fb79aa06e2267e39ed5958bf4eb51487f8 100644 (file)
@@ -14,8 +14,7 @@
 
 use infer::{InferCtxt, InferOk};
 use infer::at::At;
-use middle::const_val::ConstVal;
-use mir::interpret::GlobalId;
+use mir::interpret::{GlobalId, ConstValue};
 use traits::{Obligation, ObligationCause, PredicateObligation, Reveal};
 use traits::project::Normalized;
 use ty::{self, Ty, TyCtxt};
@@ -195,7 +194,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
     }
 
     fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
-        if let ConstVal::Unevaluated(def_id, substs) = constant.val {
+        if let ConstValue::Unevaluated(def_id, substs) = constant.val {
             let tcx = self.infcx.tcx.global_tcx();
             if let Some(param_env) = self.tcx().lift_to_global(&self.param_env) {
                 if substs.needs_infer() || substs.has_skol() {
index d24c84b2556f860653902fb8aace1aa896b6940c..39e358803cbe84f7a148de58137875b746ba8af8 100644 (file)
@@ -172,7 +172,9 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lif
                 })
             }
             super::TraitNotObjectSafe(def_id) => Some(super::TraitNotObjectSafe(def_id)),
-            super::ConstEvalFailure(ref err) => tcx.lift(err).map(super::ConstEvalFailure),
+            super::ConstEvalFailure(ref err) => tcx.lift(&**err).map(|err| super::ConstEvalFailure(
+                err.into(),
+            )),
             super::Overflow => bug!(), // FIXME: ape ConstEvalFailure?
         }
     }
index e3fbadc271206e1cbb1a2224441f32c6203a0cf1..3718c436b3a0019fa5d42321449c0b1debabf39c 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;
+use mir::interpret::ConstValue;
 use ty::subst::Substs;
 use ty::{self, Ty, TypeFlags, TypeFoldable};
 
@@ -233,12 +233,9 @@ 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::Value(_) => {}
-            ConstVal::Unevaluated(_, substs) => {
-                self.add_flags(TypeFlags::HAS_PROJECTION);
-                self.add_substs(substs);
-            }
+        if let ConstValue::Unevaluated(_, substs) = constant.val {
+            self.add_flags(TypeFlags::HAS_PROJECTION);
+            self.add_substs(substs);
         }
     }
 
index 307e1b238386c0e912675295010249613e24e73a..f55a512908499a4b7817bea0b576ec1414d8dabc 100644 (file)
@@ -39,7 +39,7 @@
 //! These methods return true to indicate that the visitor has found what it is looking for
 //! and does not need to visit anything else.
 
-use middle::const_val::ConstVal;
+use mir::interpret::ConstValue;
 use hir::def_id::DefId;
 use ty::{self, Binder, Ty, TyCtxt, TypeFlags};
 
@@ -685,7 +685,7 @@ fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
     }
 
     fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool {
-        if let ConstVal::Unevaluated(..) = c.val {
+        if let ConstValue::Unevaluated(..) = c.val {
             let projection_flags = TypeFlags::HAS_NORMALIZABLE_PROJECTION |
                 TypeFlags::HAS_PROJECTION;
             if projection_flags.intersects(self.flags) {
index d8fa978a6a07c89f4e9e46043bd0f4adec9ee2b5..1f647d811b08931145801d1e2d974ca7a34ff68b 100644 (file)
@@ -2065,7 +2065,7 @@ pub fn eval_explicit_discr(
                     })
                 } else {
                     info!("invalid enum discriminant: {:#?}", val);
-                    ::middle::const_val::struct_error(
+                    ::mir::interpret::struct_error(
                         tcx.at(tcx.def_span(expr_did)),
                         "constant evaluation of enum discriminant resulted in non-integer",
                     ).emit();
index eadfc62244f815179f55b9264eb0f21c99b50099..229caeb95d62105d77a15051c6edacfeac18ef2e 100644 (file)
@@ -11,7 +11,7 @@
 use dep_graph::SerializedDepNodeIndex;
 use dep_graph::DepNode;
 use hir::def_id::{CrateNum, DefId, DefIndex};
-use mir::interpret::{GlobalId, ConstValue};
+use mir::interpret::GlobalId;
 use traits::query::{
     CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal, CanonicalTypeOpEqGoal,
     CanonicalTypeOpNormalizeGoal, CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpSubtypeGoal,
@@ -191,8 +191,8 @@ fn describe(tcx: TyCtxt, def_id: DefId) -> String {
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::const_value_to_allocation<'tcx> {
-    fn describe(_tcx: TyCtxt, (val, ty): (ConstValue<'tcx>, Ty<'tcx>)) -> String {
-        format!("converting value `{:?}` ({}) to an allocation", val, ty)
+    fn describe(_tcx: TyCtxt, val: &'tcx ty::Const<'tcx>) -> String {
+        format!("converting value `{:?}` to an allocation", val)
     }
 }
 
index cad3a6586829e0d348142fe3ea3d14eb259eb34f..8423b02ee7582d2e73f74f30ba285592aeffba3b 100644 (file)
@@ -145,7 +145,7 @@ fn default_span(&self, tcx: TyCtxt) -> Span {
     }
 }
 
-impl<'tcx> Key for (mir::interpret::ConstValue<'tcx>, Ty<'tcx>) {
+impl<'tcx> Key for &'tcx ty::Const<'tcx> {
     fn query_crate(&self) -> CrateNum {
         LOCAL_CRATE
     }
index 178ee7cf8e9ac1938b165b202c41c674b44c4a2b..77644cdf02b116d63e173a9d5c9f97916da3941c 100644 (file)
 use middle::stability::{self, DeprecationEntry};
 use middle::lang_items::{LanguageItems, LangItem};
 use middle::exported_symbols::{SymbolExportLevel, ExportedSymbol};
-use middle::const_val::EvalResult;
+use mir::interpret::ConstEvalResult;
 use mir::mono::{CodegenUnit, Stats};
 use mir;
-use mir::interpret::{GlobalId, Allocation, ConstValue};
+use mir::interpret::{GlobalId, Allocation};
 use session::{CompileResult, CrateDisambiguator};
 use session::config::OutputFilenames;
 use traits::{self, Vtable};
     /// Results of evaluating const items or constants embedded in
     /// other items (such as enum variant explicit discriminants).
     [] fn const_eval: const_eval_dep_node(ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
-        -> EvalResult<'tcx>,
+        -> ConstEvalResult<'tcx>,
 
     /// Converts a constant value to an constant allocation
     [] fn const_value_to_allocation: const_value_to_allocation(
-        (ConstValue<'tcx>, Ty<'tcx>)
+        &'tcx ty::Const<'tcx>
     ) -> &'tcx Allocation,
 
     [] fn check_match: CheckMatch(DefId)
@@ -570,9 +570,9 @@ fn erase_regions_ty<'tcx>(ty: Ty<'tcx>) -> DepConstructor<'tcx> {
 }
 
 fn const_value_to_allocation<'tcx>(
-    (val, ty): (ConstValue<'tcx>, Ty<'tcx>)
+    val: &'tcx ty::Const<'tcx>,
 ) -> DepConstructor<'tcx> {
-    DepConstructor::ConstValueToAllocation { val, ty }
+    DepConstructor::ConstValueToAllocation { val }
 }
 
 fn type_param_predicates<'tcx>((item_id, param_id): (DefId, DefId)) -> DepConstructor<'tcx> {
index 7603ed7102327e1b4bd9b03426a0cd3d1c761416..265c6aee397266a298e134c19063f4b7719db234 100644 (file)
@@ -14,7 +14,7 @@
 //! type equality, etc.
 
 use hir::def_id::DefId;
-use middle::const_val::ConstVal;
+use mir::interpret::ConstValue;
 use ty::subst::{Kind, UnpackedKind, Substs};
 use ty::{self, Ty, TyCtxt, TypeFoldable};
 use ty::error::{ExpectedFound, TypeError};
@@ -474,7 +474,7 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
                     return Ok(s);
                 }
                 match x.val {
-                    ConstVal::Unevaluated(def_id, substs) => {
+                    ConstValue::Unevaluated(def_id, substs) => {
                         // FIXME(eddyb) get the right param_env.
                         let param_env = ty::ParamEnv::empty();
                         match tcx.lift_to_global(&substs) {
index 79a6311185076a0b5366661722871d48ba463b25..a648dc6e7e7880a166b002760c3b6d4604c2ee2b 100644 (file)
 //! hand, though we've recently added some macros (e.g.,
 //! `BraceStructLiftImpl!`) to help with the tedium.
 
-use middle::const_val::{self, ConstVal, ConstEvalErr};
+use mir::interpret::{ConstValue, ConstEvalErr};
 use ty::{self, Lift, Ty, TyCtxt};
 use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
 use rustc_data_structures::accumulate_vec::AccumulateVec;
 use rustc_data_structures::indexed_vec::{IndexVec, Idx};
-use rustc_data_structures::sync::Lrc;
 use mir::interpret;
 
 use std::rc::Rc;
@@ -462,10 +461,11 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lif
 impl<'a, 'tcx> Lift<'tcx> for ConstEvalErr<'a> {
     type Lifted = ConstEvalErr<'tcx>;
     fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
-        tcx.lift(&*self.kind).map(|kind| {
+        tcx.lift(&self.error).map(|error| {
             ConstEvalErr {
                 span: self.span,
-                kind: Lrc::new(kind),
+                stacktrace: self.stacktrace.clone(),
+                error,
             }
         })
     }
@@ -577,7 +577,9 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lif
             PathNotFound(ref v) => PathNotFound(v.clone()),
             UnimplementedTraitSelection => UnimplementedTraitSelection,
             TypeckError => TypeckError,
-            ReferencedConstant(ref err) => ReferencedConstant(tcx.lift(err)?),
+            TooGeneric => TooGeneric,
+            CheckMatchError => CheckMatchError,
+            ReferencedConstant(ref err) => ReferencedConstant(tcx.lift(&**err)?.into()),
             OverflowNeg => OverflowNeg,
             Overflow(op) => Overflow(op),
             DivisionByZero => DivisionByZero,
@@ -588,20 +590,6 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lif
     }
 }
 
-impl<'a, 'tcx> Lift<'tcx> for const_val::ErrKind<'a> {
-    type Lifted = const_val::ErrKind<'tcx>;
-    fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
-        use middle::const_val::ErrKind::*;
-
-        Some(match *self {
-            CouldNotResolve => CouldNotResolve,
-            TypeckError => TypeckError,
-            CheckMatchError => CheckMatchError,
-            Miri(ref e, ref frames) => return tcx.lift(e).map(|e| Miri(e, frames.clone())),
-        })
-    }
-}
-
 impl<'a, 'tcx> Lift<'tcx> for ty::layout::LayoutError<'a> {
     type Lifted = ty::layout::LayoutError<'tcx>;
     fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
@@ -1139,20 +1127,24 @@ impl<'tcx> TypeFoldable<'tcx> for ty::error::TypeError<'tcx> {
     }
 }
 
-impl<'tcx> TypeFoldable<'tcx> for ConstVal<'tcx> {
+impl<'tcx> TypeFoldable<'tcx> for ConstValue<'tcx> {
     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
         match *self {
-            ConstVal::Value(v) => ConstVal::Value(v),
-            ConstVal::Unevaluated(def_id, substs) => {
-                ConstVal::Unevaluated(def_id, substs.fold_with(folder))
+            ConstValue::Scalar(v) => ConstValue::Scalar(v),
+            ConstValue::ScalarPair(a, b) => ConstValue::ScalarPair(a, b),
+            ConstValue::ByRef(alloc, offset) => ConstValue::ByRef(alloc, offset),
+            ConstValue::Unevaluated(def_id, substs) => {
+                ConstValue::Unevaluated(def_id, substs.fold_with(folder))
             }
         }
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
         match *self {
-            ConstVal::Value(_) => false,
-            ConstVal::Unevaluated(_, substs) => substs.visit_with(visitor),
+            ConstValue::Scalar(_) |
+            ConstValue::ScalarPair(_, _) |
+            ConstValue::ByRef(_, _) => false,
+            ConstValue::Unevaluated(_, substs) => substs.visit_with(visitor),
         }
     }
 }
index 186ebd73b4cc5acdae44f9f0a98b4560a8b199d5..996ebd722fd4d3bf4393a72b1bf7442a45e1dab9 100644 (file)
@@ -12,7 +12,7 @@
 
 use hir::def_id::DefId;
 
-use middle::const_val::ConstVal;
+use mir::interpret::ConstValue;
 use middle::region;
 use polonius_engine::Atom;
 use rustc_data_structures::indexed_vec::Idx;
@@ -20,7 +20,7 @@
 use ty::{self, AdtDef, TypeFlags, Ty, TyCtxt, TypeFoldable};
 use ty::{Slice, TyS, ParamEnvAnd, ParamEnv};
 use util::captures::Captures;
-use mir::interpret::{Scalar, Pointer, Value, ConstValue};
+use mir::interpret::{Scalar, Pointer, Value};
 
 use std::iter;
 use std::cmp::Ordering;
@@ -1859,7 +1859,7 @@ pub fn to_opt_closure_kind(&self) -> Option<ty::ClosureKind> {
 pub struct Const<'tcx> {
     pub ty: Ty<'tcx>,
 
-    pub val: ConstVal<'tcx>,
+    pub val: ConstValue<'tcx>,
 }
 
 impl<'tcx> Const<'tcx> {
@@ -1870,15 +1870,15 @@ pub fn unevaluated(
         ty: Ty<'tcx>,
     ) -> &'tcx Self {
         tcx.mk_const(Const {
-            val: ConstVal::Unevaluated(def_id, substs),
+            val: ConstValue::Unevaluated(def_id, substs),
             ty,
         })
     }
 
     #[inline]
-    pub fn from_const_val(
+    pub fn from_const_value(
         tcx: TyCtxt<'_, '_, 'tcx>,
-        val: ConstVal<'tcx>,
+        val: ConstValue<'tcx>,
         ty: Ty<'tcx>,
     ) -> &'tcx Self {
         tcx.mk_const(Const {
@@ -1887,15 +1887,6 @@ pub fn from_const_val(
         })
     }
 
-    #[inline]
-    pub fn from_const_value(
-        tcx: TyCtxt<'_, '_, 'tcx>,
-        val: ConstValue<'tcx>,
-        ty: Ty<'tcx>,
-    ) -> &'tcx Self {
-        Self::from_const_val(tcx, ConstVal::Value(val), ty)
-    }
-
     #[inline]
     pub fn from_byval_value(
         tcx: TyCtxt<'_, '_, 'tcx>,
@@ -1956,34 +1947,22 @@ pub fn to_bits(
         }
         let ty = tcx.lift_to_global(&ty).unwrap();
         let size = tcx.layout_of(ty).ok()?.size;
-        match self.val {
-            ConstVal::Value(val) => val.to_bits(size),
-            _ => None,
-        }
+        self.val.to_bits(size)
     }
 
     #[inline]
     pub fn to_ptr(&self) -> Option<Pointer> {
-        match self.val {
-            ConstVal::Value(val) => val.to_ptr(),
-            _ => None,
-        }
+        self.val.to_ptr()
     }
 
     #[inline]
     pub fn to_byval_value(&self) -> Option<Value> {
-        match self.val {
-            ConstVal::Value(val) => val.to_byval_value(),
-            _ => None,
-        }
+        self.val.to_byval_value()
     }
 
     #[inline]
     pub fn to_scalar(&self) -> Option<Scalar> {
-        match self.val {
-            ConstVal::Value(val) => val.to_scalar(),
-            _ => None,
-        }
+        self.val.to_scalar()
     }
 
     #[inline]
@@ -1995,10 +1974,7 @@ pub fn assert_bits(
         assert_eq!(self.ty, ty.value);
         let ty = tcx.lift_to_global(&ty).unwrap();
         let size = tcx.layout_of(ty).ok()?.size;
-        match self.val {
-            ConstVal::Value(val) => val.to_bits(size),
-            _ => None,
-        }
+        self.val.to_bits(size)
     }
 
     #[inline]
index ebe88d60ed12f0ec9b624d4744d10603b67e2f78..d12f73144269bf7e87676fb038526149b34d2008 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;
+use mir::interpret::ConstValue;
 use ty::{self, Ty};
 use rustc_data_structures::small_vec::SmallVec;
 use rustc_data_structures::accumulate_vec::IntoIter as AccIntoIter;
@@ -141,11 +141,8 @@ 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::Value(_) => {}
-        ConstVal::Unevaluated(_, substs) => {
-            stack.extend(substs.types().rev());
-        }
+    if let ConstValue::Unevaluated(_, substs) = constant.val {
+        stack.extend(substs.types().rev());
     }
     stack.push(constant.ty);
 }
index 62fed1ecb668aa5402809263a630db9d6733c01b..5376acca0d8cdabf5402fc13631a2731f63abfb9 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use hir::def_id::DefId;
-use middle::const_val::ConstVal;
+use mir::interpret::ConstValue;
 use infer::InferCtxt;
 use ty::subst::Substs;
 use traits;
@@ -216,18 +216,15 @@ fn compute_projection(&mut self, data: ty::ProjectionTy<'tcx>) {
     /// into `self.out`.
     fn compute_const(&mut self, constant: &'tcx ty::Const<'tcx>) {
         self.require_sized(constant.ty, traits::ConstSized);
-        match constant.val {
-            ConstVal::Value(_) => {}
-            ConstVal::Unevaluated(def_id, substs) => {
-                let obligations = self.nominal_obligations(def_id, substs);
-                self.out.extend(obligations);
-
-                let predicate = ty::Predicate::ConstEvaluatable(def_id, substs);
-                let cause = self.cause(traits::MiscObligation);
-                self.out.push(traits::Obligation::new(cause,
-                                                      self.param_env,
-                                                      predicate));
-            }
+        if let ConstValue::Unevaluated(def_id, substs) = constant.val {
+            let obligations = self.nominal_obligations(def_id, substs);
+            self.out.extend(obligations);
+
+            let predicate = ty::Predicate::ConstEvaluatable(def_id, substs);
+            let cause = self.cause(traits::MiscObligation);
+            self.out.push(traits::Obligation::new(cause,
+                                                    self.param_env,
+                                                    predicate));
         }
     }
 
index ff6d711cef0c8a08ea2db8f5002ae71e8ff78863..deb8ac691fb3b2d772d6b7b17256c0bcc2d4bc8e 100644 (file)
@@ -10,7 +10,7 @@
 
 use hir::def_id::DefId;
 use hir::map::definitions::DefPathData;
-use middle::const_val::ConstVal;
+use mir::interpret::ConstValue;
 use middle::region::{self, BlockRemainder};
 use ty::subst::{self, Subst};
 use ty::{BrAnon, BrEnv, BrFresh, BrNamed};
@@ -1195,12 +1195,12 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                 TyArray(ty, sz) => {
                     print!(f, cx, write("["), print(ty), write("; "))?;
                     match sz.val {
-                        ConstVal::Value(..) => ty::tls::with(|tcx| {
-                            write!(f, "{}", sz.unwrap_usize(tcx))
-                        })?,
-                        ConstVal::Unevaluated(_def_id, _substs) => {
+                        ConstValue::Unevaluated(_def_id, _substs) => {
                             write!(f, "_")?;
                         }
+                        _ => ty::tls::with(|tcx| {
+                            write!(f, "{}", sz.unwrap_usize(tcx))
+                        })?,
                     }
                     write!(f, "]")
                 }
index 322924535d1f72baeb5588eecad1f606043e09e3..a4709739a23ddabcbb587813975a407d82fe9af3 100644 (file)
@@ -1381,7 +1381,6 @@ fn hash_stable<W: StableHasherResult>(&self,
 
 fn fetch_wasm_section(tcx: TyCtxt, id: DefId) -> (String, Vec<u8>) {
     use rustc::mir::interpret::GlobalId;
-    use rustc::middle::const_val::ConstVal;
 
     info!("loading wasm section {:?}", id);
 
@@ -1399,12 +1398,6 @@ fn fetch_wasm_section(tcx: TyCtxt, id: DefId) -> (String, Vec<u8>) {
     };
     let param_env = ty::ParamEnv::reveal_all();
     let val = tcx.const_eval(param_env.and(cid)).unwrap();
-
-    let const_val = match val.val {
-        ConstVal::Value(val) => val,
-        ConstVal::Unevaluated(..) => bug!("should be evaluated"),
-    };
-
-    let alloc = tcx.const_value_to_allocation((const_val, val.ty));
+    let alloc = tcx.const_value_to_allocation(val);
     (section.to_string(), alloc.bytes.clone())
 }
index 7c1035e2fcb8882f190d3e5e2f274bbcf834e98d..bbe0e34b48f2642bb1754c9b801b7c17de0250d2 100644 (file)
@@ -9,11 +9,12 @@
 // except according to those terms.
 
 use llvm::{self, ValueRef};
-use rustc::middle::const_val::{ConstVal, ConstEvalErr};
+use rustc::mir::interpret::ConstEvalErr;
 use rustc_mir::interpret::{read_target_uint, const_val_field};
 use rustc::hir::def_id::DefId;
 use rustc::mir;
 use rustc_data_structures::indexed_vec::Idx;
+use rustc_data_structures::sync::Lrc;
 use rustc::mir::interpret::{GlobalId, Pointer, Scalar, Allocation, ConstValue, AllocType};
 use rustc::ty::{self, Ty};
 use rustc::ty::layout::{self, HasDataLayout, LayoutOf, Size};
@@ -117,7 +118,7 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx, alloc: &Allocation) -> ValueRef {
 pub fn codegen_static_initializer<'a, 'tcx>(
     cx: &CodegenCx<'a, 'tcx>,
     def_id: DefId)
-    -> Result<ValueRef, ConstEvalErr<'tcx>>
+    -> Result<ValueRef, Lrc<ConstEvalErr<'tcx>>>
 {
     let instance = ty::Instance::mono(cx.tcx, def_id);
     let cid = GlobalId {
@@ -128,20 +129,20 @@ pub fn codegen_static_initializer<'a, 'tcx>(
     let static_ = cx.tcx.const_eval(param_env.and(cid))?;
 
     let alloc = match static_.val {
-        ConstVal::Value(ConstValue::ByRef(alloc, n)) if n.bytes() == 0 => alloc,
+        ConstValue::ByRef(alloc, n) if n.bytes() == 0 => alloc,
         _ => bug!("static const eval returned {:#?}", static_),
     };
     Ok(const_alloc_to_llvm(cx, alloc))
 }
 
 impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
-    fn const_to_const_value(
+    fn fully_evaluate(
         &mut self,
         bx: &Builder<'a, 'tcx>,
         constant: &'tcx ty::Const<'tcx>,
-    ) -> Result<ConstValue<'tcx>, ConstEvalErr<'tcx>> {
+    ) -> Result<&'tcx ty::Const<'tcx>, Lrc<ConstEvalErr<'tcx>>> {
         match constant.val {
-            ConstVal::Unevaluated(def_id, ref substs) => {
+            ConstValue::Unevaluated(def_id, ref substs) => {
                 let tcx = bx.tcx();
                 let param_env = ty::ParamEnv::reveal_all();
                 let instance = ty::Instance::resolve(tcx, param_env, def_id, substs).unwrap();
@@ -149,18 +150,17 @@ fn const_to_const_value(
                     instance,
                     promoted: None,
                 };
-                let c = tcx.const_eval(param_env.and(cid))?;
-                self.const_to_const_value(bx, c)
+                tcx.const_eval(param_env.and(cid))
             },
-            ConstVal::Value(val) => Ok(val),
+            _ => Ok(constant),
         }
     }
 
-    pub fn mir_constant_to_const_value(
+    pub fn eval_mir_constant(
         &mut self,
         bx: &Builder<'a, 'tcx>,
         constant: &mir::Constant<'tcx>,
-    ) -> Result<ConstValue<'tcx>, ConstEvalErr<'tcx>> {
+    ) -> Result<&'tcx ty::Const<'tcx>, Lrc<ConstEvalErr<'tcx>>> {
         match constant.literal {
             mir::Literal::Promoted { index } => {
                 let param_env = ty::ParamEnv::reveal_all();
@@ -173,7 +173,7 @@ pub fn mir_constant_to_const_value(
             mir::Literal::Value { value } => {
                 Ok(self.monomorphize(&value))
             }
-        }.and_then(|c| self.const_to_const_value(bx, c))
+        }.and_then(|c| self.fully_evaluate(bx, c))
     }
 
     /// process constant containing SIMD shuffle indices
@@ -182,14 +182,14 @@ pub fn simd_shuffle_indices(
         bx: &Builder<'a, 'tcx>,
         constant: &mir::Constant<'tcx>,
     ) -> (ValueRef, Ty<'tcx>) {
-        self.mir_constant_to_const_value(bx, constant)
+        self.eval_mir_constant(bx, constant)
             .and_then(|c| {
-                let field_ty = constant.ty.builtin_index().unwrap();
-                let fields = match constant.ty.sty {
+                let field_ty = c.ty.builtin_index().unwrap();
+                let fields = match c.ty.sty {
                     ty::TyArray(_, n) => n.unwrap_usize(bx.tcx()),
                     ref other => bug!("invalid simd shuffle type: {}", other),
                 };
-                let values: Result<Vec<ValueRef>, _> = (0..fields).map(|field| {
+                let values: Result<Vec<ValueRef>, Lrc<_>> = (0..fields).map(|field| {
                     let field = const_val_field(
                         bx.tcx(),
                         ty::ParamEnv::reveal_all(),
@@ -197,7 +197,6 @@ pub fn simd_shuffle_indices(
                         None,
                         mir::Field::new(field as usize),
                         c,
-                        constant.ty,
                     )?;
                     if let Some(prim) = field.to_scalar() {
                         let layout = bx.cx.layout_of(field_ty);
@@ -214,7 +213,7 @@ pub fn simd_shuffle_indices(
                     }
                 }).collect();
                 let llval = C_struct(bx.cx, &values?, false);
-                Ok((llval, constant.ty))
+                Ok((llval, c.ty))
             })
             .unwrap_or_else(|e| {
                 e.report_as_error(
index 9f32b41cb13e7913b9f8d6e5d7f0fc6a84d5e091..3d3a4400bd8108abca11973e5693f839dbc5fc32 100644 (file)
@@ -9,12 +9,13 @@
 // except according to those terms.
 
 use llvm::{ValueRef, LLVMConstInBoundsGEP};
-use rustc::middle::const_val::ConstEvalErr;
+use rustc::mir::interpret::ConstEvalErr;
 use rustc::mir;
 use rustc::mir::interpret::ConstValue;
 use rustc::ty;
 use rustc::ty::layout::{self, Align, LayoutOf, TyLayout};
 use rustc_data_structures::indexed_vec::Idx;
+use rustc_data_structures::sync::Lrc;
 
 use base;
 use common::{self, CodegenCx, C_null, C_undef, C_usize};
@@ -95,16 +96,16 @@ pub fn new_zst(cx: &CodegenCx<'a, 'tcx>,
     }
 
     pub fn from_const(bx: &Builder<'a, 'tcx>,
-                      val: ConstValue<'tcx>,
-                      ty: ty::Ty<'tcx>)
-                      -> Result<OperandRef<'tcx>, ConstEvalErr<'tcx>> {
-        let layout = bx.cx.layout_of(ty);
+                      val: &'tcx ty::Const<'tcx>)
+                      -> Result<OperandRef<'tcx>, Lrc<ConstEvalErr<'tcx>>> {
+        let layout = bx.cx.layout_of(val.ty);
 
         if layout.is_zst() {
             return Ok(OperandRef::new_zst(bx.cx, layout));
         }
 
-        let val = match val {
+        let val = match val.val {
+            ConstValue::Unevaluated(..) => bug!(),
             ConstValue::Scalar(x) => {
                 let scalar = match layout.abi {
                     layout::Abi::Scalar(ref x) => x,
@@ -408,8 +409,8 @@ pub fn codegen_operand(&mut self,
 
             mir::Operand::Constant(ref constant) => {
                 let ty = self.monomorphize(&constant.ty);
-                self.mir_constant_to_const_value(bx, constant)
-                    .and_then(|c| OperandRef::from_const(bx, c, ty))
+                self.eval_mir_constant(bx, constant)
+                    .and_then(|c| OperandRef::from_const(bx, c))
                     .unwrap_or_else(|err| {
                         match constant.literal {
                             mir::Literal::Promoted { .. } => {
index 41024e60202739161e46548566c4764385f8ac24..83361ea57c371e49aac538747b06130ed0351874 100644 (file)
@@ -12,8 +12,6 @@
 use self::Usefulness::*;
 use self::WitnessPreference::*;
 
-use rustc::middle::const_val::ConstVal;
-
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::indexed_vec::Idx;
 
@@ -544,14 +542,9 @@ fn max_slice_length<'p, 'a: 'p, 'tcx: 'a, I>(
 
     for row in patterns {
         match *row.kind {
-            PatternKind::Constant {
-                value: const_val @ &ty::Const {
-                    val: ConstVal::Value(..),
-                    ..
-                }
-            } => {
-                if let Some(ptr) = const_val.to_ptr() {
-                    let is_array_ptr = const_val.ty
+            PatternKind::Constant { value } => {
+                if let Some(ptr) = value.to_ptr() {
+                    let is_array_ptr = value.ty
                         .builtin_deref(true)
                         .and_then(|t| t.ty.builtin_index())
                         .map_or(false, |t| t == cx.tcx.types.u8);
@@ -933,13 +926,14 @@ fn slice_pat_covered_by_constructor<'tcx>(
     suffix: &[Pattern<'tcx>]
 ) -> Result<bool, ErrorReported> {
     let data: &[u8] = match *ctor {
-        ConstantValue(&ty::Const { val: ConstVal::Value(const_val), ty }) => {
-            let val = match const_val {
-                ConstValue::ByRef(..) => bug!("unexpected ConstValue::ByRef"),
+        ConstantValue(const_val) => {
+            let val = match const_val.val {
+                ConstValue::Unevaluated(..) |
+                ConstValue::ByRef(..) => bug!("unexpected ConstValue: {:?}", const_val),
                 ConstValue::Scalar(val) | ConstValue::ScalarPair(val, _) => val,
             };
             if let Ok(ptr) = val.to_ptr() {
-                let is_array_ptr = ty
+                let is_array_ptr = const_val.ty
                     .builtin_deref(true)
                     .and_then(|t| t.ty.builtin_index())
                     .map_or(false, |t| t == tcx.types.u8);
index 19b3654d2c7dc123756d2e825e037219b4245dae..e04cdcfa02773f520d4d0c1c06b78b133f78b775 100644 (file)
@@ -140,13 +140,13 @@ fn report_inlining_errors(&self, pat_span: Span) {
                 }
                 PatternError::FloatBug => {
                     // FIXME(#31407) this is only necessary because float parsing is buggy
-                    ::rustc::middle::const_val::struct_error(
+                    ::rustc::mir::interpret::struct_error(
                         self.tcx.at(pat_span),
                         "could not evaluate float literal (see issue #31407)",
                     ).emit();
                 }
                 PatternError::NonConstPath(span) => {
-                    ::rustc::middle::const_val::struct_error(
+                    ::rustc::mir::interpret::struct_error(
                         self.tcx.at(span),
                         "runtime values cannot be referenced in patterns",
                     ).emit();
index 3f3e29a808a4f725d9a6634ed40716cd3ce27277..4d0e3e826e8789f01efa54b5c2328aea90093929 100644 (file)
@@ -18,7 +18,6 @@
 
 use interpret::{const_val_field, const_variant_index, self};
 
-use rustc::middle::const_val::ConstVal;
 use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability};
 use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, Value};
 use rustc::ty::{self, TyCtxt, AdtDef, Ty, Region};
@@ -122,13 +121,6 @@ pub enum PatternKind<'tcx> {
     },
 }
 
-fn print_const_val(value: &ty::Const, f: &mut fmt::Formatter) -> fmt::Result {
-    match value.val {
-        ConstVal::Value(..) => fmt_const_val(f, value),
-        ConstVal::Unevaluated(..) => bug!("{:?} not printable in a pattern", value)
-    }
-}
-
 impl<'tcx> fmt::Display for Pattern<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self.kind {
@@ -236,15 +228,15 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                 write!(f, "{}", subpattern)
             }
             PatternKind::Constant { value } => {
-                print_const_val(value, f)
+                fmt_const_val(f, value)
             }
             PatternKind::Range { lo, hi, end } => {
-                print_const_val(lo, f)?;
+                fmt_const_val(f, lo)?;
                 match end {
                     RangeEnd::Included => write!(f, "...")?,
                     RangeEnd::Excluded => write!(f, "..")?,
                 }
-                print_const_val(hi, f)
+                fmt_const_val(f, hi)
             }
             PatternKind::Slice { ref prefix, ref slice, ref suffix } |
             PatternKind::Array { ref prefix, ref slice, ref suffix } => {
@@ -795,13 +787,10 @@ fn const_to_pat(
         debug!("const_to_pat: cv={:#?}", cv);
         let adt_subpattern = |i, variant_opt| {
             let field = Field::new(i);
-            let val = match cv.val {
-                ConstVal::Value(miri) => const_val_field(
-                    self.tcx, self.param_env, instance,
-                    variant_opt, field, miri, cv.ty,
-                ).expect("field access failed"),
-                _ => bug!("{:#?} is not a valid adt", cv),
-            };
+            let val = const_val_field(
+                self.tcx, self.param_env, instance,
+                variant_opt, field, cv,
+            ).expect("field access failed");
             self.const_to_pat(instance, val, id, span)
         };
         let adt_subpatterns = |n, variant_opt| {
@@ -840,24 +829,18 @@ fn const_to_pat(
                 PatternKind::Wild
             },
             ty::TyAdt(adt_def, substs) if adt_def.is_enum() => {
-                match cv.val {
-                    ConstVal::Value(val) => {
-                        let variant_index = const_variant_index(
-                            self.tcx, self.param_env, instance, val, cv.ty
-                        ).expect("const_variant_index failed");
-                        let subpatterns = adt_subpatterns(
-                            adt_def.variants[variant_index].fields.len(),
-                            Some(variant_index),
-                        );
-                        PatternKind::Variant {
-                            adt_def,
-                            substs,
-                            variant_index,
-                            subpatterns,
-                        }
-                    },
-                    ConstVal::Unevaluated(..) =>
-                        span_bug!(span, "{:#?} is not a valid enum constant", cv),
+                let variant_index = const_variant_index(
+                    self.tcx, self.param_env, instance, cv
+                ).expect("const_variant_index failed");
+                let subpatterns = adt_subpatterns(
+                    adt_def.variants[variant_index].fields.len(),
+                    Some(variant_index),
+                );
+                PatternKind::Variant {
+                    adt_def,
+                    substs,
+                    variant_index,
+                    subpatterns,
                 }
             },
             ty::TyAdt(adt_def, _) => {
index 592c9dbe6ffe4bd93eac6cbdf9ce83f154594b0f..35422b11bd733714524b7aa9c24289079b654a0c 100644 (file)
@@ -1,6 +1,5 @@
 use rustc::hir;
-use rustc::middle::const_val::{ConstEvalErr, ErrKind};
-use rustc::middle::const_val::ErrKind::{TypeckError, CheckMatchError};
+use rustc::mir::interpret::{ConstEvalErr};
 use rustc::mir;
 use rustc::ty::{self, TyCtxt, Ty, Instance};
 use rustc::ty::layout::{self, LayoutOf, Primitive};
@@ -18,7 +17,6 @@
 
 use std::fmt;
 use std::error::Error;
-use rustc_data_structures::sync::Lrc;
 
 pub fn mk_borrowck_eval_cx<'a, 'mir, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
@@ -106,7 +104,8 @@ pub fn value_to_const_value<'tcx>(
             let (frames, span) = ecx.generate_stacktrace(None);
             let err = ConstEvalErr {
                 span,
-                kind: ErrKind::Miri(err, frames).into(),
+                error: err,
+                stacktrace: frames,
             };
             err.report_as_error(
                 ecx.tcx,
@@ -426,13 +425,13 @@ pub fn const_val_field<'a, 'tcx>(
     instance: ty::Instance<'tcx>,
     variant: Option<usize>,
     field: mir::Field,
-    value: ConstValue<'tcx>,
-    ty: Ty<'tcx>,
-) -> ::rustc::middle::const_val::EvalResult<'tcx> {
-    trace!("const_val_field: {:?}, {:?}, {:?}, {:?}", instance, field, value, ty);
+    value: &'tcx ty::Const<'tcx>,
+) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> {
+    trace!("const_val_field: {:?}, {:?}, {:?}", instance, field, value);
     let mut ecx = mk_eval_cx(tcx, instance, param_env).unwrap();
     let result = (|| {
-        let value = ecx.const_value_to_value(value, ty)?;
+        let ty = value.ty;
+        let value = ecx.const_to_value(value.val)?;
         let layout = ecx.layout_of(ty)?;
         let (ptr, align) = match value {
             Value::ByRef(ptr, align) => (ptr, align),
@@ -467,11 +466,11 @@ pub fn const_val_field<'a, 'tcx>(
     })();
     result.map_err(|err| {
         let (trace, span) = ecx.generate_stacktrace(None);
-        let err = ErrKind::Miri(err, trace);
         ConstEvalErr {
-            kind: err.into(),
+            error: err,
+            stacktrace: trace,
             span,
-        }
+        }.into()
     })
 }
 
@@ -479,30 +478,29 @@ pub fn const_variant_index<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     instance: ty::Instance<'tcx>,
-    val: ConstValue<'tcx>,
-    ty: Ty<'tcx>,
+    val: &'tcx ty::Const<'tcx>,
 ) -> EvalResult<'tcx, usize> {
-    trace!("const_variant_index: {:?}, {:?}, {:?}", instance, val, ty);
+    trace!("const_variant_index: {:?}, {:?}", instance, val);
     let mut ecx = mk_eval_cx(tcx, instance, param_env).unwrap();
-    let value = ecx.const_value_to_value(val, ty)?;
+    let value = ecx.const_to_value(val.val)?;
     let (ptr, align) = match value {
         Value::ScalarPair(..) | Value::Scalar(_) => {
-            let layout = ecx.layout_of(ty)?;
+            let layout = ecx.layout_of(val.ty)?;
             let ptr = ecx.memory.allocate(layout.size, layout.align, Some(MemoryKind::Stack))?.into();
-            ecx.write_value_to_ptr(value, ptr, layout.align, ty)?;
+            ecx.write_value_to_ptr(value, ptr, layout.align, val.ty)?;
             (ptr, layout.align)
         },
         Value::ByRef(ptr, align) => (ptr, align),
     };
     let place = Place::from_scalar_ptr(ptr, align);
-    ecx.read_discriminant_as_variant_index(place, ty)
+    ecx.read_discriminant_as_variant_index(place, val.ty)
 }
 
 pub fn const_value_to_allocation_provider<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    (val, ty): (ConstValue<'tcx>, Ty<'tcx>),
+    val: &'tcx ty::Const<'tcx>,
 ) -> &'tcx Allocation {
-    match val {
+    match val.val {
         ConstValue::ByRef(alloc, offset) => {
             assert_eq!(offset.bytes(), 0);
             return alloc;
@@ -515,20 +513,20 @@ pub fn const_value_to_allocation_provider<'a, 'tcx>(
             ty::ParamEnv::reveal_all(),
             CompileTimeEvaluator,
             ());
-        let value = ecx.const_value_to_value(val, ty)?;
-        let layout = ecx.layout_of(ty)?;
+        let value = ecx.const_to_value(val.val)?;
+        let layout = ecx.layout_of(val.ty)?;
         let ptr = ecx.memory.allocate(layout.size, layout.align, Some(MemoryKind::Stack))?;
-        ecx.write_value_to_ptr(value, ptr.into(), layout.align, ty)?;
+        ecx.write_value_to_ptr(value, ptr.into(), layout.align, val.ty)?;
         let alloc = ecx.memory.get(ptr.alloc_id)?;
         Ok(tcx.intern_const_alloc(alloc.clone()))
     };
-    result().expect("unable to convert ConstVal to Allocation")
+    result().expect("unable to convert ConstValue to Allocation")
 }
 
 pub fn const_eval_provider<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
-) -> ::rustc::middle::const_val::EvalResult<'tcx> {
+) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> {
     trace!("const eval: {:?}", key);
     let cid = key.value;
     let def_id = cid.instance.def.def_id();
@@ -540,9 +538,10 @@ pub fn const_eval_provider<'a, 'tcx>(
         // Do match-check before building MIR
         if tcx.check_match(def_id).is_err() {
             return Err(ConstEvalErr {
-                kind: Lrc::new(CheckMatchError),
+                error: EvalErrorKind::CheckMatchError.into(),
+                stacktrace: vec![],
                 span,
-            });
+            }.into());
         }
 
         if let hir::BodyOwnerKind::Const = tcx.hir.body_owner_kind(id) {
@@ -552,9 +551,10 @@ pub fn const_eval_provider<'a, 'tcx>(
         // Do not continue into miri if typeck errors occurred; it will fail horribly
         if tables.tainted_by_errors {
             return Err(ConstEvalErr {
-                kind: Lrc::new(TypeckError),
+                error: EvalErrorKind::CheckMatchError.into(),
+                stacktrace: vec![],
                 span,
-            });
+            }.into());
         }
     };
 
@@ -566,15 +566,15 @@ pub fn const_eval_provider<'a, 'tcx>(
         Ok(value_to_const_value(&ecx, val, miri_ty))
     }).map_err(|err| {
         let (trace, span) = ecx.generate_stacktrace(None);
-        let err = ErrKind::Miri(err, trace);
         let err = ConstEvalErr {
-            kind: err.into(),
+            error: err,
+            stacktrace: trace,
             span,
         };
         if tcx.is_static(def_id).is_some() {
             err.report_as_error(ecx.tcx, "could not evaluate static initializer");
         }
-        err
+        err.into()
     })
 }
 
index ea667273ecead0b3fc066d528d8fa9502055a244..6dc65a2404d11ab9d0c947ffb05181856cbcffe4 100644 (file)
@@ -3,14 +3,13 @@
 use rustc::hir::def_id::DefId;
 use rustc::hir::def::Def;
 use rustc::hir::map::definitions::DefPathData;
-use rustc::middle::const_val::ConstVal;
 use rustc::mir;
 use rustc::ty::layout::{self, Size, Align, HasDataLayout, IntegerExt, LayoutOf, TyLayout};
 use rustc::ty::subst::{Subst, Substs};
 use rustc::ty::{self, Ty, TyCtxt, TypeAndMut};
 use rustc::ty::query::TyCtxtAt;
 use rustc_data_structures::indexed_vec::{IndexVec, Idx};
-use rustc::middle::const_val::FrameInfo;
+use rustc::mir::interpret::FrameInfo;
 use syntax::codemap::{self, Span};
 use syntax::ast::Mutability;
 use rustc::mir::interpret::{
@@ -233,12 +232,18 @@ pub fn str_to_value(&mut self, s: &str) -> EvalResult<'tcx, Value> {
         Ok(Scalar::Ptr(ptr).to_value_with_len(s.len() as u64, self.tcx.tcx))
     }
 
-    pub fn const_value_to_value(
+    pub fn const_to_value(
         &mut self,
         val: ConstValue<'tcx>,
-        _ty: Ty<'tcx>,
     ) -> EvalResult<'tcx, Value> {
         match val {
+            ConstValue::Unevaluated(def_id, substs) => {
+                let instance = self.resolve(def_id, substs)?;
+                self.read_global_as_value(GlobalId {
+                    instance,
+                    promoted: None,
+                })
+            }
             ConstValue::ByRef(alloc, offset) => {
                 // FIXME: Allocate new AllocId for all constants inside
                 let id = self.memory.allocate_value(alloc.clone(), Some(MemoryKind::Stack))?;
@@ -249,23 +254,6 @@ pub fn const_value_to_value(
         }
     }
 
-    pub(super) fn const_to_value(
-        &mut self,
-        const_val: &ConstVal<'tcx>,
-        ty: Ty<'tcx>
-    ) -> EvalResult<'tcx, Value> {
-        match *const_val {
-            ConstVal::Unevaluated(def_id, substs) => {
-                let instance = self.resolve(def_id, substs)?;
-                self.read_global_as_value(GlobalId {
-                    instance,
-                    promoted: None,
-                }, ty)
-            }
-            ConstVal::Value(val) => self.const_value_to_value(val, ty)
-        }
-    }
-
     pub(super) fn resolve(&self, def_id: DefId, substs: &'tcx Substs<'tcx>) -> EvalResult<'tcx, ty::Instance<'tcx>> {
         trace!("resolve: {:?}, {:#?}", def_id, substs);
         trace!("substs: {:#?}", self.substs());
@@ -280,7 +268,7 @@ pub(super) fn resolve(&self, def_id: DefId, substs: &'tcx Substs<'tcx>) -> EvalR
             self.param_env,
             def_id,
             substs,
-        ).ok_or_else(|| EvalErrorKind::TypeckError.into()) // turn error prop into a panic to expose associated type in const issue
+        ).ok_or_else(|| EvalErrorKind::TooGeneric.into())
     }
 
     pub(super) fn type_is_sized(&self, ty: Ty<'tcx>) -> bool {
@@ -739,7 +727,7 @@ pub(super) fn eval_rvalue_into_place(
                                     self.param_env,
                                     def_id,
                                     substs,
-                                ).ok_or_else(|| EvalErrorKind::TypeckError.into());
+                                ).ok_or_else(|| EvalErrorKind::TooGeneric.into());
                                 let fn_ptr = self.memory.create_fn_alloc(instance?);
                                 let valty = ValTy {
                                     value: Value::Scalar(fn_ptr.into()),
@@ -849,14 +837,14 @@ pub fn eval_operand(&mut self, op: &mir::Operand<'tcx>) -> EvalResult<'tcx, ValT
                 use rustc::mir::Literal;
                 let mir::Constant { ref literal, .. } = **constant;
                 let value = match *literal {
-                    Literal::Value { ref value } => self.const_to_value(&value.val, ty)?,
+                    Literal::Value { ref value } => self.const_to_value(value.val)?,
 
                     Literal::Promoted { index } => {
                         let instance = self.frame().instance;
                         self.read_global_as_value(GlobalId {
                             instance,
                             promoted: Some(index),
-                        }, ty)?
+                        })?
                     }
                 };
 
@@ -1036,18 +1024,9 @@ pub fn write_discriminant_value(
         Ok(())
     }
 
-    pub fn read_global_as_value(&mut self, gid: GlobalId<'tcx>, ty: Ty<'tcx>) -> EvalResult<'tcx, Value> {
-        if self.tcx.is_static(gid.instance.def_id()).is_some() {
-            let alloc_id = self
-                .tcx
-                .alloc_map
-                .lock()
-                .intern_static(gid.instance.def_id());
-            let layout = self.layout_of(ty)?;
-            return Ok(Value::ByRef(Scalar::Ptr(alloc_id.into()), layout.align))
-        }
+    pub fn read_global_as_value(&mut self, gid: GlobalId<'tcx>) -> EvalResult<'tcx, Value> {
         let cv = self.const_eval(gid)?;
-        self.const_to_value(&cv.val, ty)
+        self.const_to_value(cv.val)
     }
 
     pub fn const_eval(&self, gid: GlobalId<'tcx>) -> EvalResult<'tcx, &'tcx ty::Const<'tcx>> {
index ad571fbe90d5d0918a585da04bd817a35fa2dfa9..9e5b6be3e9122eff1ff95d39bcf8e458002e7fb6 100644 (file)
@@ -7,7 +7,6 @@
 use rustc::ty::query::TyCtxtAt;
 use rustc::ty::layout::{self, Align, TargetDataLayout, Size};
 use syntax::ast::Mutability;
-use rustc::middle::const_val::ConstVal;
 
 use rustc_data_structures::fx::{FxHashSet, FxHashMap};
 use rustc::mir::interpret::{Pointer, AllocId, Allocation, AccessKind, Value,
@@ -285,16 +284,12 @@ fn const_eval_static(&self, def_id: DefId) -> EvalResult<'tcx, &'tcx Allocation>
             instance,
             promoted: None,
         };
-        self.tcx.const_eval(ParamEnv::reveal_all().and(gid)).map_err(|_| {
+        self.tcx.const_eval(ParamEnv::reveal_all().and(gid)).map_err(|err| {
             // no need to report anything, the const_eval call takes care of that for statics
             assert!(self.tcx.is_static(def_id).is_some());
-            EvalErrorKind::TypeckError.into()
+            EvalErrorKind::ReferencedConstant(err).into()
         }).map(|val| {
-            let const_val = match val.val {
-                ConstVal::Value(val) => val,
-                ConstVal::Unevaluated(..) => bug!("should be evaluated"),
-            };
-            self.tcx.const_value_to_allocation((const_val, val.ty))
+            self.tcx.const_value_to_allocation(val)
         })
     }
 
index 8a2a78daa357052ec896c71bf4b81a629b15c604..8320add715769580611c146e197b535233f98e21 100644 (file)
@@ -95,9 +95,10 @@ pub fn binary_op(
         // These ops can have an RHS with a different numeric type.
         if right_kind.is_int() && (bin_op == Shl || bin_op == Shr) {
             let signed = left_layout.abi.is_signed();
+            let mut oflo = (r as u32 as u128) != r;
             let mut r = r as u32;
             let size = left_layout.size.bits() as u32;
-            let oflo = r >= size;
+            oflo |= r >= size;
             if oflo {
                 r %= size;
             }
index a65ee065ca68fff1550f749f95e362bf4fbdcb2b..3a046cd800a3e1db0419999a10f86ed804c40d61 100644 (file)
 
 use rustc::hir::map as hir_map;
 use rustc::hir::def_id::DefId;
-use rustc::middle::const_val::ConstVal;
 use rustc::mir::interpret::{AllocId, ConstValue};
 use rustc::middle::lang_items::{ExchangeMallocFnLangItem, StartFnLangItem};
 use rustc::ty::subst::Substs;
@@ -1210,15 +1209,12 @@ fn collect_neighbours<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         match tcx.const_eval(param_env.and(cid)) {
             Ok(val) => collect_const(tcx, val, instance.substs, output),
             Err(err) => {
-                use rustc::middle::const_val::ErrKind;
                 use rustc::mir::interpret::EvalErrorKind;
-                if let ErrKind::Miri(ref miri, ..) = *err.kind {
-                    if let EvalErrorKind::ReferencedConstant(_) = miri.kind {
-                        err.report_as_error(
-                            tcx.at(mir.promoted[i].span),
-                            "erroneous constant used",
-                        );
-                    }
+                if let EvalErrorKind::ReferencedConstant(_) = err.error.kind {
+                    err.report_as_error(
+                        tcx.at(mir.promoted[i].span),
+                        "erroneous constant used",
+                    );
                 }
             },
         }
@@ -1243,7 +1239,7 @@ fn collect_const<'a, 'tcx>(
     debug!("visiting const {:?}", *constant);
 
     let val = match constant.val {
-        ConstVal::Unevaluated(def_id, substs) => {
+        ConstValue::Unevaluated(def_id, substs) => {
             let param_env = ty::ParamEnv::reveal_all();
             let substs = tcx.subst_and_normalize_erasing_regions(
                 param_substs,
@@ -1274,16 +1270,16 @@ fn collect_const<'a, 'tcx>(
         _ => constant.val,
     };
     match val {
-        ConstVal::Unevaluated(..) => bug!("const eval yielded unevaluated const"),
-        ConstVal::Value(ConstValue::ScalarPair(Scalar::Ptr(a), Scalar::Ptr(b))) => {
+        ConstValue::Unevaluated(..) => bug!("const eval yielded unevaluated const"),
+        ConstValue::ScalarPair(Scalar::Ptr(a), Scalar::Ptr(b)) => {
             collect_miri(tcx, a.alloc_id, output);
             collect_miri(tcx, b.alloc_id, output);
         }
-        ConstVal::Value(ConstValue::ScalarPair(_, Scalar::Ptr(ptr))) |
-        ConstVal::Value(ConstValue::ScalarPair(Scalar::Ptr(ptr), _)) |
-        ConstVal::Value(ConstValue::Scalar(Scalar::Ptr(ptr))) =>
+        ConstValue::ScalarPair(_, Scalar::Ptr(ptr)) |
+        ConstValue::ScalarPair(Scalar::Ptr(ptr), _) |
+        ConstValue::Scalar(Scalar::Ptr(ptr)) =>
             collect_miri(tcx, ptr.alloc_id, output),
-        ConstVal::Value(ConstValue::ByRef(alloc, _offset)) => {
+        ConstValue::ByRef(alloc, _offset) => {
             for &id in alloc.relocations.values() {
                 collect_miri(tcx, id, output);
             }
index 24382815084619dee7a74c01d18979e26b5309a1..3b3c28f6ae2655c2dbd9df61e247ad1be3e33b81 100644 (file)
@@ -17,7 +17,7 @@
 use rustc::mir::{NullOp, StatementKind, Statement, BasicBlock, LocalKind};
 use rustc::mir::{TerminatorKind, ClearCrossCrate, SourceInfo, BinOp, ProjectionElem};
 use rustc::mir::visit::{Visitor, PlaceContext};
-use rustc::middle::const_val::{ConstVal, ConstEvalErr, ErrKind};
+use rustc::mir::interpret::ConstEvalErr;
 use rustc::ty::{TyCtxt, self, Instance};
 use rustc::mir::interpret::{Value, Scalar, GlobalId, EvalResult};
 use interpret::EvalContext;
@@ -45,8 +45,11 @@ fn run_pass<'a, 'tcx>(&self,
             return;
         }
         match tcx.describe_def(source.def_id) {
-            // skip statics because they'll be evaluated by miri anyway
+            // skip statics/consts because they'll be evaluated by miri anyway
+            Some(Def::Const(..)) |
             Some(Def::Static(..)) => return,
+            // we still run on associated constants, because they might not get evaluated
+            // within the current crate
             _ => {},
         }
         trace!("ConstProp starting for {:?}", source.def_id);
@@ -145,7 +148,8 @@ fn use_ecx<F, T>(
                 let (frames, span) = self.ecx.generate_stacktrace(None);
                 let err = ConstEvalErr {
                     span,
-                    kind: ErrKind::Miri(err, frames).into(),
+                    error: err,
+                    stacktrace: frames,
                 };
                 err.report_as_lint(
                     self.ecx.tcx,
@@ -159,54 +163,30 @@ fn use_ecx<F, T>(
         r
     }
 
-    fn const_eval(&mut self, cid: GlobalId<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {
-        let value = match self.tcx.const_eval(self.param_env.and(cid)) {
-            Ok(val) => val,
-            Err(err) => {
-                err.report_as_error(
-                    self.tcx.at(err.span),
-                    "constant evaluation error",
-                );
-                return None;
-            },
-        };
-        let val = match value.val {
-            ConstVal::Value(v) => {
-                self.use_ecx(source_info, |this| this.ecx.const_value_to_value(v, value.ty))?
-            },
-            _ => bug!("eval produced: {:?}", value),
-        };
-        let val = (val, value.ty, source_info.span);
-        trace!("evaluated {:?} to {:?}", cid, val);
-        Some(val)
-    }
-
     fn eval_constant(
         &mut self,
         c: &Constant<'tcx>,
         source_info: SourceInfo,
     ) -> Option<Const<'tcx>> {
         match c.literal {
-            Literal::Value { value } => match value.val {
-                ConstVal::Value(v) => {
-                    let v = self.use_ecx(source_info, |this| {
-                        this.ecx.const_value_to_value(v, value.ty)
-                    })?;
-                    Some((v, value.ty, c.span))
-                },
-                ConstVal::Unevaluated(did, substs) => {
-                    let instance = Instance::resolve(
-                        self.tcx,
-                        self.param_env,
-                        did,
-                        substs,
-                    )?;
-                    let cid = GlobalId {
-                        instance,
-                        promoted: None,
-                    };
-                    self.const_eval(cid, source_info)
-                },
+            Literal::Value { value } => {
+                self.ecx.tcx.span = source_info.span;
+                match self.ecx.const_to_value(value.val) {
+                    Ok(val) => Some((val, value.ty, c.span)),
+                    Err(error) => {
+                        let (stacktrace, span) = self.ecx.generate_stacktrace(None);
+                        let err = ConstEvalErr {
+                            span,
+                            error,
+                            stacktrace,
+                        };
+                        err.report_as_error(
+                            self.tcx.at(source_info.span),
+                            "could not evaluate constant",
+                        );
+                        None
+                    },
+                }
             },
             // evaluate the promoted and replace the constant with the evaluated result
             Literal::Promoted { index } => {
index 6448ba17e3464480eb8d2c478dead103c1a5e1d0..144ebce76e14cbe01f5137a041c4d77249ae76c1 100644 (file)
@@ -20,7 +20,7 @@
 use rustc_data_structures::fx::FxHashSet;
 use rustc::hir;
 use rustc::hir::def_id::DefId;
-use rustc::middle::const_val::ConstVal;
+use rustc::mir::interpret::ConstValue;
 use rustc::traits::{self, TraitEngine};
 use rustc::ty::{self, TyCtxt, Ty, TypeFoldable};
 use rustc::ty::cast::CastTy;
@@ -611,7 +611,7 @@ fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
             }
             Operand::Constant(ref constant) => {
                 if let Literal::Value {
-                    value: &ty::Const { val: ConstVal::Unevaluated(def_id, _), ty, .. }
+                    value: &ty::Const { val: ConstValue::Unevaluated(def_id, _), ty, .. }
                 } = constant.literal {
                     // Don't peek inside trait associated constants.
                     if self.tcx.trait_of_item(def_id).is_some() {
index e2cf714f0ead307175ee91bdee7762c53c119b64..4e716fb207fab080b4f8287f3cfe47ceea865e92 100644 (file)
@@ -16,7 +16,9 @@ pub fn target() -> Result<Target, String> {
                 vec!["-s".to_string(),
                      "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string(),
                      "-s".to_string(),
-                     "ABORTING_MALLOC=0".to_string()]);
+                     "ABORTING_MALLOC=0".to_string(),
+                     "-s".to_string(),
+                     "WASM=0".to_string()]);
 
     let opts = TargetOptions {
         dynamic_linking: false,
index 76219c6971b22773ba7024b23a61f1ad01feefd4..e276dcff0601dca195a53556bd141d68365b28bc 100644 (file)
@@ -1203,9 +1203,14 @@ fn coerce_inner<'a>(&mut self,
                                       "supposed to be part of a block tail expression, but the \
                                        expression is empty");
                         });
-                        fcx.suggest_mismatched_types_on_tail(&mut db, expr,
-                                                             expected, found,
-                                                             cause.span, blk_id);
+                        fcx.suggest_mismatched_types_on_tail(
+                            &mut db,
+                            expr,
+                            expected,
+                            found,
+                            cause.span,
+                            blk_id,
+                        );
                     }
                     _ => {
                         db = fcx.report_mismatched_types(cause, expected, found, err);
index 8582eb3fbd87cf2fb230bd96b3c078ad4ea4918f..08d8dd2e498b68ff67c437929978b883bd124abe 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::iter;
-
 use check::FnCtxt;
 use rustc::infer::InferOk;
 use rustc::traits::ObligationCause;
@@ -140,25 +138,12 @@ pub fn demand_coerce_diag(&self,
             }
         }
 
-        if let Some((sp, msg, suggestion)) = self.check_ref(expr, checked_ty, expected) {
-            err.span_suggestion(sp, msg, suggestion);
-        } else if !self.check_for_cast(&mut err, expr, expr_ty, expected) {
-            let methods = self.get_conversion_methods(expr.span, expected, checked_ty);
-            if let Ok(expr_text) = self.tcx.sess.codemap().span_to_snippet(expr.span) {
-                let suggestions = iter::repeat(expr_text).zip(methods.iter())
-                    .map(|(receiver, method)| format!("{}.{}()", receiver, method.ident))
-                    .collect::<Vec<_>>();
-                if !suggestions.is_empty() {
-                    err.span_suggestions(expr.span,
-                                         "try using a conversion method",
-                                         suggestions);
-                }
-            }
-        }
+        self.suggest_ref_or_into(&mut err, expr, expected, expr_ty);
+
         (expected, Some(err))
     }
 
-    fn get_conversion_methods(&self, span: Span, expected: Ty<'tcx>, checked_ty: Ty<'tcx>)
+    pub fn get_conversion_methods(&self, span: Span, expected: Ty<'tcx>, checked_ty: Ty<'tcx>)
                               -> Vec<AssociatedItem> {
         let mut methods = self.probe_for_return_type(span,
                                                      probe::Mode::MethodCall,
@@ -261,19 +246,24 @@ fn can_use_as_ref(&self, expr: &hir::Expr) -> Option<(Span, &'static str, String
     /// In addition of this check, it also checks between references mutability state. If the
     /// expected is mutable but the provided isn't, maybe we could just say "Hey, try with
     /// `&mut`!".
-    fn check_ref(&self,
+    pub fn check_ref(&self,
                  expr: &hir::Expr,
                  checked_ty: Ty<'tcx>,
                  expected: Ty<'tcx>)
                  -> Option<(Span, &'static str, String)> {
-        let sp = expr.span;
+        let cm = self.sess().codemap();
+        // Use the callsite's span if this is a macro call. #41858
+        let sp = cm.call_span_if_macro(expr.span);
+        if !cm.span_to_filename(sp).is_real() {
+            return None;
+        }
+
         match (&expected.sty, &checked_ty.sty) {
             (&ty::TyRef(_, exp, _), &ty::TyRef(_, check, _)) => match (&exp.sty, &check.sty) {
                 (&ty::TyStr, &ty::TyArray(arr, _)) |
                 (&ty::TyStr, &ty::TySlice(arr)) if arr == self.tcx.types.u8 => {
                     if let hir::ExprLit(_) = expr.node {
-                        let sp = self.sess().codemap().call_span_if_macro(expr.span);
-                        if let Ok(src) = self.tcx.sess.codemap().span_to_snippet(sp) {
+                        if let Ok(src) = cm.span_to_snippet(sp) {
                             return Some((sp,
                                          "consider removing the leading `b`",
                                          src[1..].to_string()));
@@ -283,8 +273,7 @@ fn check_ref(&self,
                 (&ty::TyArray(arr, _), &ty::TyStr) |
                 (&ty::TySlice(arr), &ty::TyStr) if arr == self.tcx.types.u8 => {
                     if let hir::ExprLit(_) = expr.node {
-                        let sp = self.sess().codemap().call_span_if_macro(expr.span);
-                        if let Ok(src) = self.tcx.sess.codemap().span_to_snippet(sp) {
+                        if let Ok(src) = cm.span_to_snippet(sp) {
                             return Some((sp,
                                          "consider adding a leading `b`",
                                          format!("b{}", src)));
@@ -311,9 +300,7 @@ fn check_ref(&self,
                                                        checked_ty),
                 };
                 if self.can_coerce(ref_ty, expected) {
-                    // Use the callsite's span if this is a macro call. #41858
-                    let sp = self.sess().codemap().call_span_if_macro(expr.span);
-                    if let Ok(src) = self.tcx.sess.codemap().span_to_snippet(sp) {
+                    if let Ok(src) = cm.span_to_snippet(sp) {
                         let sugg_expr = match expr.node { // parenthesize if needed (Issue #46756)
                             hir::ExprCast(_, _) | hir::ExprBinary(_, _, _) => format!("({})", src),
                             _ => src,
@@ -342,11 +329,14 @@ fn check_ref(&self,
                 // a macro; if so, it's hard to extract the text and make a good
                 // suggestion, so don't bother.)
                 if self.infcx.can_sub(self.param_env, checked, &expected).is_ok() &&
-                   expr.span.ctxt().outer().expn_info().is_none() {
+                   sp.ctxt().outer().expn_info().is_none() {
                     match expr.node {
                         // Maybe remove `&`?
                         hir::ExprAddrOf(_, ref expr) => {
-                            if let Ok(code) = self.tcx.sess.codemap().span_to_snippet(expr.span) {
+                            if !cm.span_to_filename(expr.span).is_real() {
+                                return None;
+                            }
+                            if let Ok(code) = cm.span_to_snippet(expr.span) {
                                 return Some((sp, "consider removing the borrow", code));
                             }
                         }
@@ -355,9 +345,9 @@ fn check_ref(&self,
                         _ => {
                             if !self.infcx.type_moves_by_default(self.param_env,
                                                                 checked,
-                                                                expr.span) {
-                                let sp = self.sess().codemap().call_span_if_macro(expr.span);
-                                if let Ok(code) = self.tcx.sess.codemap().span_to_snippet(sp) {
+                                                                sp) {
+                                let sp = cm.call_span_if_macro(sp);
+                                if let Ok(code) = cm.span_to_snippet(sp) {
                                     return Some((sp,
                                                  "consider dereferencing the borrow",
                                                  format!("*{}", code)));
@@ -372,7 +362,7 @@ fn check_ref(&self,
         None
     }
 
-    fn check_for_cast(&self,
+    pub fn check_for_cast(&self,
                       err: &mut DiagnosticBuilder<'tcx>,
                       expr: &hir::Expr,
                       checked_ty: Ty<'tcx>,
index f8c4bfc9ad723ab3f88d72abbe9a677b0a74b1b8..0185d00518699b0b53cc09681b665ce8dba83034 100644 (file)
 use std::collections::hash_map::Entry;
 use std::cmp;
 use std::fmt::Display;
+use std::iter;
 use std::mem::replace;
 use std::ops::{self, Deref};
 use rustc_target::spec::abi::Abi;
@@ -4539,10 +4540,32 @@ pub fn suggest_mismatched_types_on_tail(&self,
                                             cause_span: Span,
                                             blk_id: ast::NodeId) {
         self.suggest_missing_semicolon(err, expression, expected, cause_span);
-
         if let Some((fn_decl, can_suggest)) = self.get_fn_decl(blk_id) {
             self.suggest_missing_return_type(err, &fn_decl, expected, found, can_suggest);
         }
+        self.suggest_ref_or_into(err, expression, expected, found);
+    }
+
+    pub fn suggest_ref_or_into(
+        &self,
+        err: &mut DiagnosticBuilder<'tcx>,
+        expr: &hir::Expr,
+        expected: Ty<'tcx>,
+        found: Ty<'tcx>,
+    ) {
+        if let Some((sp, msg, suggestion)) = self.check_ref(expr, found, expected) {
+            err.span_suggestion(sp, msg, suggestion);
+        } else if !self.check_for_cast(err, expr, found, expected) {
+            let methods = self.get_conversion_methods(expr.span, expected, found);
+            if let Ok(expr_text) = self.sess().codemap().span_to_snippet(expr.span) {
+                let suggestions = iter::repeat(expr_text).zip(methods.iter())
+                    .map(|(receiver, method)| format!("{}.{}()", receiver, method.ident))
+                    .collect::<Vec<_>>();
+                if !suggestions.is_empty() {
+                    err.span_suggestions(expr.span, "try using a conversion method", suggestions);
+                }
+            }
+        }
     }
 
     /// A common error is to forget to add a semicolon at the end of a block:
index e9f8aeb9ec8c53b8bf98fd56722a550ed06bb3bb..8cdffcd558d75cff4c1c5ab6e2ab82945fe776fa 100644 (file)
@@ -29,7 +29,7 @@
 use syntax::symbol::{Symbol, InternedString};
 use syntax_pos::{self, DUMMY_SP, Pos, FileName};
 
-use rustc::middle::const_val::ConstVal;
+use rustc::mir::interpret::ConstValue;
 use rustc::middle::privacy::AccessLevels;
 use rustc::middle::resolve_lifetime as rl;
 use rustc::ty::fold::TypeFolder;
@@ -3014,7 +3014,7 @@ fn clean(&self, cx: &DocContext) -> Type {
             ty::TySlice(ty) => Slice(box ty.clean(cx)),
             ty::TyArray(ty, n) => {
                 let mut n = cx.tcx.lift(&n).unwrap();
-                if let ConstVal::Unevaluated(def_id, substs) = n.val {
+                if let ConstValue::Unevaluated(def_id, substs) = n.val {
                     let param_env = cx.tcx.param_env(def_id);
                     let cid = GlobalId {
                         instance: ty::Instance::new(def_id, substs),
@@ -4096,14 +4096,14 @@ fn name_from_pat(p: &hir::Pat) -> String {
 
 fn print_const(cx: &DocContext, n: &ty::Const) -> String {
     match n.val {
-        ConstVal::Unevaluated(def_id, _) => {
+        ConstValue::Unevaluated(def_id, _) => {
             if let Some(node_id) = cx.tcx.hir.as_local_node_id(def_id) {
                 print_const_expr(cx, cx.tcx.hir.body_owned_by(node_id))
             } else {
                 inline::print_inlined_const(cx, def_id)
             }
         },
-        ConstVal::Value(..) => {
+        _ => {
             let mut s = String::new();
             ::rustc::mir::fmt_const_val(&mut s, n).unwrap();
             // array lengths are obviously usize
index bb996e00d352abfe586884082ceb33beb4051530..01eb1ce7407be16fa868b1a45e2d356201dc1ba7 100644 (file)
                             var res = buildHrefAndPath(obj);
                             obj.displayPath = pathSplitter(res[0]);
                             obj.fullPath = obj.displayPath + obj.name;
-                            if (obj.ty === TY_KEYWORD) {
-                                // To be sure than it isn't considered as duplicate with items.
-                                obj.fullPath += '|k';
-                            }
+                            // To be sure than it some items aren't considered as duplicate.
+                            obj.fullPath += '|' + obj.ty;
                             obj.href = res[1];
                             out.push(obj);
                             if (out.length >= MAX_RESULTS) {
index 1dacf99b64b7808406388285638d8e0b8b71c786..90f054186d16118a7a1ae3a841240c21daa65f73 100644 (file)
@@ -796,7 +796,10 @@ pub fn park() {
     let mut m = thread.inner.lock.lock().unwrap();
     match thread.inner.state.compare_exchange(EMPTY, PARKED, SeqCst, SeqCst) {
         Ok(_) => {}
-        Err(NOTIFIED) => return, // notified after we locked
+        Err(NOTIFIED) => {
+            thread.inner.state.store(EMPTY, SeqCst);
+            return;
+        } // should consume this notification, so prohibit spurious wakeups in next park.
         Err(_) => panic!("inconsistent park state"),
     }
     loop {
@@ -882,7 +885,10 @@ pub fn park_timeout(dur: Duration) {
     let m = thread.inner.lock.lock().unwrap();
     match thread.inner.state.compare_exchange(EMPTY, PARKED, SeqCst, SeqCst) {
         Ok(_) => {}
-        Err(NOTIFIED) => return, // notified after we locked
+        Err(NOTIFIED) => {
+            thread.inner.state.store(EMPTY, SeqCst);
+            return;
+        } // should consume this notification, so prohibit spurious wakeups in next park.
         Err(_) => panic!("inconsistent park_timeout state"),
     }
 
index 92c6b1fd0b5822a0125c3d8e6bf7dad3f08821dc..39b1b342eac3149752718d55ad5d48e24e3669c9 100644 (file)
 #![deny(const_err)]
 
 pub const A: i8 = -std::i8::MIN; //~ ERROR const_err
-//~^ ERROR this constant cannot be used
-//~| ERROR this expression will panic at runtime
 pub const B: u8 = 200u8 + 200u8; //~ ERROR const_err
-//~^ ERROR this constant cannot be used
 pub const C: u8 = 200u8 * 4; //~ ERROR const_err
-//~^ ERROR this constant cannot be used
 pub const D: u8 = 42u8 - (42u8 + 1); //~ ERROR const_err
-//~^ ERROR this constant cannot be used
 pub const E: u8 = [5u8][1]; //~ ERROR const_err
-//~| ERROR this constant cannot be used
 
 fn main() {
     let _a = A;
index 4a5e78b381ed049bdace21dc842ded1f758f6ed9..f2ee8a7078c7c0d9f94dbeb3a2c874be32da4055 100644 (file)
 #![deny(const_err)]
 
 pub const A: i8 = -std::i8::MIN;
-//~^ ERROR E0080
-//~| ERROR attempt to negate with overflow
-//~| ERROR this expression will panic at runtime
-//~| ERROR this constant cannot be used
+//~^ ERROR this constant cannot be used
 pub const B: i8 = A;
 //~^ ERROR const_err
 //~| ERROR const_err
index f77603b3ebafcf83a884e12316dec5e278220fd5..8683f6a0231921c0e89d84a9dc36fe68edfc6e58 100644 (file)
@@ -23,9 +23,10 @@ fn black_box<T>(_: T) {
 // Make sure that the two uses get two errors.
 const FOO: u8 = [5u8][1];
 //~^ ERROR constant evaluation error
-//~| ERROR constant evaluation error
 //~| index out of bounds: the len is 1 but the index is 1
 
 fn main() {
     black_box((FOO, FOO));
+    //~^ ERROR referenced constant has errors
+    //~| ERROR could not evaluate constant
 }
index 7b5db7a4f6db07923a9b71b0ee23114a20a6f0d9..88fc51827753532d7107dc574df8d298f8b086fa 100644 (file)
      //~^ ERROR this constant cannot be used
     (
      i8::MIN - 1,
-     //~^ ERROR attempt to subtract with overflow
      );
 
 const VALS_I16: (i16,) =
      //~^ ERROR this constant cannot be used
     (
      i16::MIN - 1,
-     //~^ ERROR attempt to subtract with overflow
      );
 
 const VALS_I32: (i32,) =
      //~^ ERROR this constant cannot be used
     (
      i32::MIN - 1,
-     //~^ ERROR attempt to subtract with overflow
      );
 
 const VALS_I64: (i64,) =
      //~^ ERROR this constant cannot be used
     (
      i64::MIN - 1,
-     //~^ ERROR attempt to subtract with overflow
      );
 
 const VALS_U8: (u8,) =
      //~^ ERROR this constant cannot be used
     (
      u8::MIN - 1,
-     //~^ ERROR attempt to subtract with overflow
      );
 
 const VALS_U16: (u16,) = (
      //~^ ERROR this constant cannot be used
      u16::MIN - 1,
-     //~^ ERROR attempt to subtract with overflow
      );
 
 const VALS_U32: (u32,) = (
      //~^ ERROR this constant cannot be used
      u32::MIN - 1,
-     //~^ ERROR attempt to subtract with overflow
      );
 
 const VALS_U64: (u64,) =
      //~^ ERROR this constant cannot be used
     (
      u64::MIN - 1,
-     //~^ ERROR attempt to subtract with overflow
      );
 
 fn main() {
index ce4dc72555dc0172afcbe78078a113f23f90f17e..1878daea93198a40cf169e407b43f3c33fd2cc2a 100644 (file)
      //~^ ERROR this constant cannot be used
     (
      i8::MAX + 1,
-     //~^ ERROR attempt to add with overflow
      );
 
 const VALS_I16: (i16,) =
      //~^ ERROR this constant cannot be used
     (
      i16::MAX + 1,
-     //~^ ERROR attempt to add with overflow
      );
 
 const VALS_I32: (i32,) =
      //~^ ERROR this constant cannot be used
     (
      i32::MAX + 1,
-     //~^ ERROR attempt to add with overflow
      );
 
 const VALS_I64: (i64,) =
      //~^ ERROR this constant cannot be used
     (
      i64::MAX + 1,
-     //~^ ERROR attempt to add with overflow
      );
 
 const VALS_U8: (u8,) =
      //~^ ERROR this constant cannot be used
     (
      u8::MAX + 1,
-     //~^ ERROR attempt to add with overflow
      );
 
 const VALS_U16: (u16,) = (
      //~^ ERROR this constant cannot be used
      u16::MAX + 1,
-     //~^ ERROR attempt to add with overflow
      );
 
 const VALS_U32: (u32,) = (
      //~^ ERROR this constant cannot be used
      u32::MAX + 1,
-     //~^ ERROR attempt to add with overflow
      );
 
 const VALS_U64: (u64,) =
      //~^ ERROR this constant cannot be used
     (
      u64::MAX + 1,
-     //~^ ERROR attempt to add with overflow
      );
 
 fn main() {
index 88eb14a133019a33659cd2d699396ce7f8c376e7..f3d28295bf81ce19a0116590d5d796c3884aad62 100644 (file)
      //~^ ERROR this constant cannot be used
     (
      i8::MIN * 2,
-     //~^ ERROR attempt to multiply with overflow
      );
 
 const VALS_I16: (i16,) =
      //~^ ERROR this constant cannot be used
     (
      i16::MIN * 2,
-     //~^ ERROR attempt to multiply with overflow
      );
 
 const VALS_I32: (i32,) =
      //~^ ERROR this constant cannot be used
     (
      i32::MIN * 2,
-     //~^ ERROR attempt to multiply with overflow
      );
 
 const VALS_I64: (i64,) =
      //~^ ERROR this constant cannot be used
     (
      i64::MIN * 2,
-     //~^ ERROR attempt to multiply with overflow
      );
 
 const VALS_U8: (u8,) =
      //~^ ERROR this constant cannot be used
     (
      u8::MAX * 2,
-     //~^ ERROR attempt to multiply with overflow
      );
 
 const VALS_U16: (u16,) = (
      //~^ ERROR this constant cannot be used
      u16::MAX * 2,
-     //~^ ERROR attempt to multiply with overflow
      );
 
 const VALS_U32: (u32,) = (
      //~^ ERROR this constant cannot be used
      u32::MAX * 2,
-     //~^ ERROR attempt to multiply with overflow
      );
 
 const VALS_U64: (u64,) =
      //~^ ERROR this constant cannot be used
     (
      u64::MAX * 2,
-     //~^ ERROR attempt to multiply with overflow
      );
 
 fn main() {
diff --git a/src/test/rustdoc-js/macro-check.js b/src/test/rustdoc-js/macro-check.js
new file mode 100644 (file)
index 0000000..fb61688
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2018 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.
+
+// ignore-order
+
+const QUERY = 'panic';
+
+const EXPECTED = {
+    'others': [
+        { 'path': 'std', 'name': 'panic', ty: 14 }, // 15 is for macros
+        { 'path': 'std', 'name': 'panic', ty: 0 }, // 0 is for modules
+    ],
+};
index 3580950854dc7f087b90990b6719d34d07a28cb4..8bc302a2befa4fca221547969703380a6e194c38 100644 (file)
@@ -1,8 +1,10 @@
-warning: attempt to subtract with overflow
-  --> $DIR/conditional_array_execution.rs:15:19
+warning: this constant cannot be used
+  --> $DIR/conditional_array_execution.rs:15:1
    |
 LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
-   |                   ^^^^^
+   | ^^^^^^^^^^^^^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                   |
+   |                   attempt to subtract with overflow
    |
 note: lint level defined here
   --> $DIR/conditional_array_execution.rs:11:9
@@ -10,16 +12,8 @@ note: lint level defined here
 LL | #![warn(const_err)]
    |         ^^^^^^^^^
 
-warning: this constant cannot be used
-  --> $DIR/conditional_array_execution.rs:15:1
-   |
-LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
-   | ^^^^^^^^^^^^^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                   |
-   |                   attempt to subtract with overflow
-
-warning: referenced constant
-  --> $DIR/conditional_array_execution.rs:20:20
+warning: referenced constant has errors
+  --> $DIR/conditional_array_execution.rs:19:20
    |
 LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
    |                   ----- attempt to subtract with overflow
@@ -28,13 +22,13 @@ LL |     println!("{}", FOO);
    |                    ^^^
 
 warning: this expression will panic at runtime
-  --> $DIR/conditional_array_execution.rs:20:20
+  --> $DIR/conditional_array_execution.rs:19:20
    |
 LL |     println!("{}", FOO);
    |                    ^^^ referenced constant has errors
 
-error[E0080]: referenced constant
-  --> $DIR/conditional_array_execution.rs:20:5
+error[E0080]: referenced constant has errors
+  --> $DIR/conditional_array_execution.rs:19:5
    |
 LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
    |                   ----- attempt to subtract with overflow
@@ -45,7 +39,7 @@ LL |     println!("{}", FOO);
    = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 
 error[E0080]: erroneous constant used
-  --> $DIR/conditional_array_execution.rs:20:5
+  --> $DIR/conditional_array_execution.rs:19:5
    |
 LL |     println!("{}", FOO);
    |     ^^^^^^^^^^^^^^^---^^
@@ -54,8 +48,8 @@ LL |     println!("{}", FOO);
    |
    = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 
-error[E0080]: referenced constant
-  --> $DIR/conditional_array_execution.rs:20:20
+error[E0080]: referenced constant has errors
+  --> $DIR/conditional_array_execution.rs:19:20
    |
 LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
    |                   ----- attempt to subtract with overflow
@@ -64,7 +58,7 @@ LL |     println!("{}", FOO);
    |                    ^^^
 
 error[E0080]: erroneous constant used
-  --> $DIR/conditional_array_execution.rs:20:20
+  --> $DIR/conditional_array_execution.rs:19:20
    |
 LL |     println!("{}", FOO);
    |                    ^^^ referenced constant has errors
index ac555b25afdcd60647c1ec6200190777c544fa0a..99487eb49792324137d03fea2eae59ee674e757a 100644 (file)
@@ -13,8 +13,7 @@
 const X: u32 = 5;
 const Y: u32 = 6;
 const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
-//~^ WARN attempt to subtract with overflow
-//~| WARN this constant cannot be used
+//~^ WARN this constant cannot be used
 
 fn main() {
     println!("{}", FOO);
index 64010c946a7f1de863670d6d429a076f2b1f8846..649da03a5e7fae60d713e0f1eb96805432233e56 100644 (file)
@@ -1,8 +1,10 @@
-warning: attempt to subtract with overflow
-  --> $DIR/conditional_array_execution.rs:15:19
+warning: this constant cannot be used
+  --> $DIR/conditional_array_execution.rs:15:1
    |
 LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
-   |                   ^^^^^
+   | ^^^^^^^^^^^^^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                   |
+   |                   attempt to subtract with overflow
    |
 note: lint level defined here
   --> $DIR/conditional_array_execution.rs:11:9
@@ -10,16 +12,8 @@ note: lint level defined here
 LL | #![warn(const_err)]
    |         ^^^^^^^^^
 
-warning: this constant cannot be used
-  --> $DIR/conditional_array_execution.rs:15:1
-   |
-LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
-   | ^^^^^^^^^^^^^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                   |
-   |                   attempt to subtract with overflow
-
-warning: referenced constant
-  --> $DIR/conditional_array_execution.rs:20:20
+warning: referenced constant has errors
+  --> $DIR/conditional_array_execution.rs:19:20
    |
 LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
    |                   ----- attempt to subtract with overflow
@@ -28,13 +22,13 @@ LL |     println!("{}", FOO);
    |                    ^^^
 
 warning: this expression will panic at runtime
-  --> $DIR/conditional_array_execution.rs:20:20
+  --> $DIR/conditional_array_execution.rs:19:20
    |
 LL |     println!("{}", FOO);
    |                    ^^^ referenced constant has errors
 
-error[E0080]: referenced constant
-  --> $DIR/conditional_array_execution.rs:20:20
+error[E0080]: referenced constant has errors
+  --> $DIR/conditional_array_execution.rs:19:20
    |
 LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
    |                   ----- attempt to subtract with overflow
@@ -43,7 +37,7 @@ LL |     println!("{}", FOO);
    |                    ^^^
 
 error[E0080]: erroneous constant used
-  --> $DIR/conditional_array_execution.rs:20:20
+  --> $DIR/conditional_array_execution.rs:19:20
    |
 LL |     println!("{}", FOO);
    |                    ^^^ referenced constant has errors
index 3bde12ade90c3c2ff7ca8ccb95cd1c0b77963e95..5819e6a9254a759bcb63a8c2d0cdf89740824b02 100644 (file)
@@ -1,15 +1,3 @@
-warning: attempt to subtract with overflow
-  --> $DIR/issue-43197.rs:20:20
-   |
-LL |     const X: u32 = 0-1;
-   |                    ^^^
-   |
-note: lint level defined here
-  --> $DIR/issue-43197.rs:11:9
-   |
-LL | #![warn(const_err)]
-   |         ^^^^^^^^^
-
 warning: this constant cannot be used
   --> $DIR/issue-43197.rs:20:5
    |
@@ -17,23 +5,23 @@ LL |     const X: u32 = 0-1;
    |     ^^^^^^^^^^^^^^^---^
    |                    |
    |                    attempt to subtract with overflow
-
-warning: attempt to subtract with overflow
-  --> $DIR/issue-43197.rs:23:24
    |
-LL |     const Y: u32 = foo(0-1);
-   |                        ^^^
+note: lint level defined here
+  --> $DIR/issue-43197.rs:11:9
+   |
+LL | #![warn(const_err)]
+   |         ^^^^^^^^^
 
 warning: this constant cannot be used
-  --> $DIR/issue-43197.rs:23:5
+  --> $DIR/issue-43197.rs:22:5
    |
 LL |     const Y: u32 = foo(0-1);
    |     ^^^^^^^^^^^^^^^^^^^---^^
    |                        |
    |                        attempt to subtract with overflow
 
-warning: referenced constant
-  --> $DIR/issue-43197.rs:26:23
+warning: referenced constant has errors
+  --> $DIR/issue-43197.rs:24:23
    |
 LL |     const X: u32 = 0-1;
    |                    --- attempt to subtract with overflow
@@ -42,28 +30,28 @@ LL |     println!("{} {}", X, Y);
    |                       ^
 
 warning: this expression will panic at runtime
-  --> $DIR/issue-43197.rs:26:23
+  --> $DIR/issue-43197.rs:24:23
    |
 LL |     println!("{} {}", X, Y);
    |                       ^ referenced constant has errors
 
-warning: referenced constant
-  --> $DIR/issue-43197.rs:26:26
+warning: referenced constant has errors
+  --> $DIR/issue-43197.rs:24:26
    |
 LL |     const Y: u32 = foo(0-1);
    |                        --- attempt to subtract with overflow
-...
+LL |     //~^ WARN this constant cannot be used
 LL |     println!("{} {}", X, Y);
    |                          ^
 
 warning: this expression will panic at runtime
-  --> $DIR/issue-43197.rs:26:26
+  --> $DIR/issue-43197.rs:24:26
    |
 LL |     println!("{} {}", X, Y);
    |                          ^ referenced constant has errors
 
-error[E0080]: referenced constant
-  --> $DIR/issue-43197.rs:26:5
+error[E0080]: referenced constant has errors
+  --> $DIR/issue-43197.rs:24:5
    |
 LL |     const X: u32 = 0-1;
    |                    --- attempt to subtract with overflow
@@ -74,7 +62,7 @@ LL |     println!("{} {}", X, Y);
    = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 
 error[E0080]: erroneous constant used
-  --> $DIR/issue-43197.rs:26:5
+  --> $DIR/issue-43197.rs:24:5
    |
 LL |     println!("{} {}", X, Y);
    |     ^^^^^^^^^^^^^^^^^^-^^^^^
@@ -83,23 +71,23 @@ LL |     println!("{} {}", X, Y);
    |
    = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 
-error[E0080]: referenced constant
-  --> $DIR/issue-43197.rs:26:26
+error[E0080]: referenced constant has errors
+  --> $DIR/issue-43197.rs:24:26
    |
 LL |     const Y: u32 = foo(0-1);
    |                        --- attempt to subtract with overflow
-...
+LL |     //~^ WARN this constant cannot be used
 LL |     println!("{} {}", X, Y);
    |                          ^
 
 error[E0080]: erroneous constant used
-  --> $DIR/issue-43197.rs:26:26
+  --> $DIR/issue-43197.rs:24:26
    |
 LL |     println!("{} {}", X, Y);
    |                          ^ referenced constant has errors
 
-error[E0080]: referenced constant
-  --> $DIR/issue-43197.rs:26:23
+error[E0080]: referenced constant has errors
+  --> $DIR/issue-43197.rs:24:23
    |
 LL |     const X: u32 = 0-1;
    |                    --- attempt to subtract with overflow
@@ -108,7 +96,7 @@ LL |     println!("{} {}", X, Y);
    |                       ^
 
 error[E0080]: erroneous constant used
-  --> $DIR/issue-43197.rs:26:23
+  --> $DIR/issue-43197.rs:24:23
    |
 LL |     println!("{} {}", X, Y);
    |                       ^ referenced constant has errors
index 03aa65eb274671716088717e03ab1db03b76693e..9304af7b811cf7832ce7f494a96f63140fe878c2 100644 (file)
@@ -18,11 +18,9 @@ const fn foo(x: u32) -> u32 {
 
 fn main() {
     const X: u32 = 0-1;
-    //~^ WARN attempt to subtract with overflow
-    //~| WARN this constant cannot be used
+    //~^ WARN this constant cannot be used
     const Y: u32 = foo(0-1);
-    //~^ WARN attempt to subtract with overflow
-    //~| WARN this constant cannot be used
+    //~^ WARN this constant cannot be used
     println!("{} {}", X, Y);
     //~^ WARN this expression will panic at runtime
     //~| WARN this expression will panic at runtime
index 071d878730744b409a2b47cb32040ef5ab4a91eb..bf864d81ea3ca179f34825c5b01ab59f13daf2de 100644 (file)
@@ -1,15 +1,3 @@
-warning: attempt to subtract with overflow
-  --> $DIR/issue-43197.rs:20:20
-   |
-LL |     const X: u32 = 0-1;
-   |                    ^^^
-   |
-note: lint level defined here
-  --> $DIR/issue-43197.rs:11:9
-   |
-LL | #![warn(const_err)]
-   |         ^^^^^^^^^
-
 warning: this constant cannot be used
   --> $DIR/issue-43197.rs:20:5
    |
@@ -17,23 +5,23 @@ LL |     const X: u32 = 0-1;
    |     ^^^^^^^^^^^^^^^---^
    |                    |
    |                    attempt to subtract with overflow
-
-warning: attempt to subtract with overflow
-  --> $DIR/issue-43197.rs:23:24
    |
-LL |     const Y: u32 = foo(0-1);
-   |                        ^^^
+note: lint level defined here
+  --> $DIR/issue-43197.rs:11:9
+   |
+LL | #![warn(const_err)]
+   |         ^^^^^^^^^
 
 warning: this constant cannot be used
-  --> $DIR/issue-43197.rs:23:5
+  --> $DIR/issue-43197.rs:22:5
    |
 LL |     const Y: u32 = foo(0-1);
    |     ^^^^^^^^^^^^^^^^^^^---^^
    |                        |
    |                        attempt to subtract with overflow
 
-warning: referenced constant
-  --> $DIR/issue-43197.rs:26:23
+warning: referenced constant has errors
+  --> $DIR/issue-43197.rs:24:23
    |
 LL |     const X: u32 = 0-1;
    |                    --- attempt to subtract with overflow
@@ -42,43 +30,43 @@ LL |     println!("{} {}", X, Y);
    |                       ^
 
 warning: this expression will panic at runtime
-  --> $DIR/issue-43197.rs:26:23
+  --> $DIR/issue-43197.rs:24:23
    |
 LL |     println!("{} {}", X, Y);
    |                       ^ referenced constant has errors
 
-warning: referenced constant
-  --> $DIR/issue-43197.rs:26:26
+warning: referenced constant has errors
+  --> $DIR/issue-43197.rs:24:26
    |
 LL |     const Y: u32 = foo(0-1);
    |                        --- attempt to subtract with overflow
-...
+LL |     //~^ WARN this constant cannot be used
 LL |     println!("{} {}", X, Y);
    |                          ^
 
 warning: this expression will panic at runtime
-  --> $DIR/issue-43197.rs:26:26
+  --> $DIR/issue-43197.rs:24:26
    |
 LL |     println!("{} {}", X, Y);
    |                          ^ referenced constant has errors
 
-error[E0080]: referenced constant
-  --> $DIR/issue-43197.rs:26:26
+error[E0080]: referenced constant has errors
+  --> $DIR/issue-43197.rs:24:26
    |
 LL |     const Y: u32 = foo(0-1);
    |                        --- attempt to subtract with overflow
-...
+LL |     //~^ WARN this constant cannot be used
 LL |     println!("{} {}", X, Y);
    |                          ^
 
 error[E0080]: erroneous constant used
-  --> $DIR/issue-43197.rs:26:26
+  --> $DIR/issue-43197.rs:24:26
    |
 LL |     println!("{} {}", X, Y);
    |                          ^ referenced constant has errors
 
-error[E0080]: referenced constant
-  --> $DIR/issue-43197.rs:26:23
+error[E0080]: referenced constant has errors
+  --> $DIR/issue-43197.rs:24:23
    |
 LL |     const X: u32 = 0-1;
    |                    --- attempt to subtract with overflow
@@ -87,7 +75,7 @@ LL |     println!("{} {}", X, Y);
    |                       ^
 
 error[E0080]: erroneous constant used
-  --> $DIR/issue-43197.rs:26:23
+  --> $DIR/issue-43197.rs:24:23
    |
 LL |     println!("{} {}", X, Y);
    |                       ^ referenced constant has errors
index ad4f08966c01220560ac2b8cbdcac60a82d9436f..eeb152e00ea477d2c5d5ea7095acfe69648e824a 100644 (file)
@@ -1,4 +1,4 @@
-error[E0080]: referenced constant
+error[E0080]: referenced constant has errors
   --> $DIR/issue-44578.rs:35:5
    |
 LL |     const AMT: usize = [A::AMT][(A::AMT > B::AMT) as usize];
@@ -19,7 +19,7 @@ LL |     println!("{}", <Bar<u16, u8> as Foo>::AMT);
    |
    = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 
-error[E0080]: referenced constant
+error[E0080]: referenced constant has errors
   --> $DIR/issue-44578.rs:35:20
    |
 LL |     const AMT: usize = [A::AMT][(A::AMT > B::AMT) as usize];
index 28a723a069edf5eda39331c0c3c14158d6198571..06174f37dcad1145896f92a9d2fa78e3e68a5c7f 100644 (file)
@@ -1,4 +1,4 @@
-error[E0080]: referenced constant
+error[E0080]: referenced constant has errors
   --> $DIR/issue-44578.rs:35:20
    |
 LL |     const AMT: usize = [A::AMT][(A::AMT > B::AMT) as usize];
index 3c59cb0e2bc727c03145f5f639a2755fc189f7fd..1e37e9498120fb64da6ba57d8feb4f03c1381103 100644 (file)
@@ -1,4 +1,4 @@
-error[E0080]: referenced constant
+error[E0080]: referenced constant has errors
   --> $DIR/issue-50814-2.rs:26:5
    |
 LL |     const BAR: usize = [5, 6, 7][T::BOO];
index 145279ccc033d71d77f70f9513d9ca8eb0a57b5f..16160207c573ba20d39f923db33cf0d30d687d6d 100644 (file)
@@ -1,4 +1,4 @@
-error[E0080]: referenced constant
+error[E0080]: referenced constant has errors
   --> $DIR/issue-50814.rs:27:5
    |
 LL |     const MAX: u8 = A::MAX + B::MAX;
index ef8fdb33d748aa578dc66abfc348905e45716c81..b7cfa949bac957f76432f4be129acd12838f1bad 100644 (file)
@@ -14,8 +14,7 @@
 #![crate_type = "lib"]
 
 pub const Z: u32 = 0 - 1;
-//~^ WARN attempt to subtract with overflow
-//~| WARN this constant cannot be used
+//~^ WARN this constant cannot be used
 
 pub type Foo = [i32; 0 - 1];
 //~^ WARN attempt to subtract with overflow
index 352289417547e20a562e339df3b2460bb93e2c96..fa3a79a5f1790b09de082fbcb3e3b21d5c8875dc 100644 (file)
@@ -1,8 +1,10 @@
-warning: attempt to subtract with overflow
-  --> $DIR/pub_const_err.rs:16:20
+warning: this constant cannot be used
+  --> $DIR/pub_const_err.rs:16:1
    |
 LL | pub const Z: u32 = 0 - 1;
-   |                    ^^^^^
+   | ^^^^^^^^^^^^^^^^^^^-----^
+   |                    |
+   |                    attempt to subtract with overflow
    |
 note: lint level defined here
   --> $DIR/pub_const_err.rs:12:9
@@ -10,22 +12,14 @@ note: lint level defined here
 LL | #![warn(const_err)]
    |         ^^^^^^^^^
 
-warning: this constant cannot be used
-  --> $DIR/pub_const_err.rs:16:1
-   |
-LL | pub const Z: u32 = 0 - 1;
-   | ^^^^^^^^^^^^^^^^^^^-----^
-   |                    |
-   |                    attempt to subtract with overflow
-
 warning: attempt to subtract with overflow
-  --> $DIR/pub_const_err.rs:20:22
+  --> $DIR/pub_const_err.rs:19:22
    |
 LL | pub type Foo = [i32; 0 - 1];
    |                      ^^^^^
 
 warning: this array length cannot be used
-  --> $DIR/pub_const_err.rs:20:22
+  --> $DIR/pub_const_err.rs:19:22
    |
 LL | pub type Foo = [i32; 0 - 1];
    |                      ^^^^^ attempt to subtract with overflow
index f65da1d8674a29105b1a1d6b0af4d9a6ae9327ac..bafa5b2f4da12ffa0efd556ac84d7bff591170ef 100644 (file)
@@ -12,8 +12,7 @@
 #![warn(const_err)]
 
 pub const Z: u32 = 0 - 1;
-//~^ WARN attempt to subtract with overflow
-//~| WARN this constant cannot be used
+//~^ WARN this constant cannot be used
 
 pub type Foo = [i32; 0 - 1];
 //~^ WARN attempt to subtract with overflow
index a6db2176011d598e61ba6147d5350c8b4aa220ea..73229c60d14dbe45a07d7d2be07afc3b25ac6ed8 100644 (file)
@@ -1,8 +1,10 @@
-warning: attempt to subtract with overflow
-  --> $DIR/pub_const_err_bin.rs:14:20
+warning: this constant cannot be used
+  --> $DIR/pub_const_err_bin.rs:14:1
    |
 LL | pub const Z: u32 = 0 - 1;
-   |                    ^^^^^
+   | ^^^^^^^^^^^^^^^^^^^-----^
+   |                    |
+   |                    attempt to subtract with overflow
    |
 note: lint level defined here
   --> $DIR/pub_const_err_bin.rs:12:9
@@ -10,22 +12,14 @@ note: lint level defined here
 LL | #![warn(const_err)]
    |         ^^^^^^^^^
 
-warning: this constant cannot be used
-  --> $DIR/pub_const_err_bin.rs:14:1
-   |
-LL | pub const Z: u32 = 0 - 1;
-   | ^^^^^^^^^^^^^^^^^^^-----^
-   |                    |
-   |                    attempt to subtract with overflow
-
 warning: attempt to subtract with overflow
-  --> $DIR/pub_const_err_bin.rs:18:22
+  --> $DIR/pub_const_err_bin.rs:17:22
    |
 LL | pub type Foo = [i32; 0 - 1];
    |                      ^^^^^
 
 warning: this array length cannot be used
-  --> $DIR/pub_const_err_bin.rs:18:22
+  --> $DIR/pub_const_err_bin.rs:17:22
    |
 LL | pub type Foo = [i32; 0 - 1];
    |                      ^^^^^ attempt to subtract with overflow
diff --git a/src/test/ui/const-eval/shift_overflow.rs b/src/test/ui/const-eval/shift_overflow.rs
new file mode 100644 (file)
index 0000000..a2c6ed3
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2018 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.
+
+enum Foo {
+    // test that we detect overflows for non-u32 discriminants
+    X = 1 << ((u32::max_value() as u64) + 1), //~ ERROR E0080
+    Y = 42,
+}
+
+
+fn main() {
+}
diff --git a/src/test/ui/const-eval/shift_overflow.stderr b/src/test/ui/const-eval/shift_overflow.stderr
new file mode 100644 (file)
index 0000000..00a7482
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0080]: could not evaluate enum discriminant
+  --> $DIR/shift_overflow.rs:13:9
+   |
+LL |     X = 1 << ((u32::max_value() as u64) + 1), //~ ERROR E0080
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to shift left with overflow
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
index 20b8865767459793351b132fe896878a2543496c..8db1411005e5772daa8548a395adc18fd16205f2 100644 (file)
 const ONE: usize = 1;
 const TWO: usize = 2;
 const LEN: usize = ONE - TWO;
-//~^ ERROR E0080
-//~| ERROR attempt to subtract with overflow
 
 fn main() {
     let a: [i8; LEN] = unimplemented!();
 //~^ ERROR E0080
 //~| ERROR E0080
+//~| ERROR E0080
+//~| ERROR E0080
 }
index 630828ef8f5178adbacc2bc7a9b4d55c4069e824..cf97a0dc5557866a674705f84fffc56b41ce1dac 100644 (file)
@@ -1,19 +1,20 @@
-error: attempt to subtract with overflow
-  --> $DIR/const-len-underflow-separate-spans.rs:17:20
+error[E0080]: referenced constant has errors
+  --> $DIR/const-len-underflow-separate-spans.rs:20:17
    |
 LL | const LEN: usize = ONE - TWO;
-   |                    ^^^^^^^^^
-   |
-   = note: #[deny(const_err)] on by default
+   |                    --------- attempt to subtract with overflow
+...
+LL |     let a: [i8; LEN] = unimplemented!();
+   |                 ^^^
 
-error[E0080]: constant evaluation error
-  --> $DIR/const-len-underflow-separate-spans.rs:17:20
+error[E0080]: could not evaluate constant
+  --> $DIR/const-len-underflow-separate-spans.rs:20:17
    |
-LL | const LEN: usize = ONE - TWO;
-   |                    ^^^^^^^^^ attempt to subtract with overflow
+LL |     let a: [i8; LEN] = unimplemented!();
+   |                 ^^^ referenced constant has errors
 
-error[E0080]: referenced constant
-  --> $DIR/const-len-underflow-separate-spans.rs:22:12
+error[E0080]: referenced constant has errors
+  --> $DIR/const-len-underflow-separate-spans.rs:20:12
    |
 LL | const LEN: usize = ONE - TWO;
    |                    --------- attempt to subtract with overflow
@@ -22,7 +23,7 @@ LL |     let a: [i8; LEN] = unimplemented!();
    |            ^^^^^^^^^
 
 error[E0080]: could not evaluate constant expression
-  --> $DIR/const-len-underflow-separate-spans.rs:22:12
+  --> $DIR/const-len-underflow-separate-spans.rs:20:12
    |
 LL |     let a: [i8; LEN] = unimplemented!();
    |            ^^^^^---^
index 12699d8b25f81750393da26779a59a5d70d020e1..041bae4a421080644c088473bf386227040f847c 100644 (file)
@@ -14,7 +14,10 @@ LL | fn main() {
    |           - expected `()` because of default return type
 ...
 LL |   let u: &str = if true { s[..2] } else { s };
-   |                           ^^^^^^ expected &str, found str
+   |                           ^^^^^^
+   |                           |
+   |                           expected &str, found str
+   |                           help: consider borrowing here: `&s[..2]`
    |
    = note: expected type `&str`
               found type `str`