]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #63203 - spastorino:is-mutable-use-place-ref, r=oli-obk
authorMazdak Farrokhzad <twingoow@gmail.com>
Fri, 2 Aug 2019 10:14:23 +0000 (12:14 +0200)
committerGitHub <noreply@github.com>
Fri, 2 Aug 2019 10:14:23 +0000 (12:14 +0200)
Make is_mutable use PlaceRef instead of it's fields

r? @oli-obk

47 files changed:
src/libcore/array.rs
src/libcore/convert.rs
src/libcore/future/future.rs
src/libcore/macros.rs
src/libcore/mem/maybe_uninit.rs
src/libcore/ptr/mod.rs
src/librustc/infer/canonical/canonicalizer.rs
src/librustc/infer/mod.rs
src/librustc/mir/interpret/allocation.rs
src/librustc/mir/interpret/error.rs
src/librustc/mir/interpret/mod.rs
src/librustc/mir/interpret/pointer.rs
src/librustc/mir/interpret/value.rs
src/librustc/mir/mod.rs
src/librustc/mir/visit.rs
src/librustc/traits/select.rs
src/librustc/ty/relate.rs
src/librustc_codegen_ssa/mir/block.rs
src/librustc_mir/borrow_check/mod.rs
src/librustc_mir/borrow_check/nll/invalidation.rs
src/librustc_mir/borrow_check/nll/type_check/mod.rs
src/librustc_mir/build/expr/as_place.rs
src/librustc_mir/build/expr/as_rvalue.rs
src/librustc_mir/const_eval.rs
src/librustc_mir/interpret/cast.rs
src/librustc_mir/interpret/eval_context.rs
src/librustc_mir/interpret/intern.rs
src/librustc_mir/interpret/intrinsics.rs
src/librustc_mir/interpret/machine.rs
src/librustc_mir/interpret/memory.rs
src/librustc_mir/interpret/operand.rs
src/librustc_mir/interpret/operator.rs
src/librustc_mir/interpret/place.rs
src/librustc_mir/interpret/snapshot.rs
src/librustc_mir/interpret/step.rs
src/librustc_mir/interpret/terminator.rs
src/librustc_mir/interpret/traits.rs
src/librustc_mir/interpret/validity.rs
src/librustc_mir/transform/const_prop.rs
src/librustc_mir/transform/generator.rs
src/libstd/ffi/c_str.rs
src/libsyntax/ext/tt/macro_rules.rs
src/libsyntax/parse/mod.rs
src/libsyntax/parse/parser.rs
src/test/ui/macros/issue-63102.rs [new file with mode: 0644]
src/test/ui/parser/issue-63135.rs [new file with mode: 0644]
src/test/ui/parser/issue-63135.stderr [new file with mode: 0644]

index 517893a1967dc63b39801bc06ec2e4e4891a2e70..b5614010e5c2f2b1730d93092b1fd6c38b7105ab 100644 (file)
 /// layout in memory of a fixed size array (for example, for unsafe
 /// initialization).
 ///
-/// Note that the traits AsRef and AsMut provide similar methods for types that
+/// Note that the traits [`AsRef`] and [`AsMut`] provide similar methods for types that
 /// may not be fixed-size arrays. Implementors should prefer those traits
 /// instead.
+///
+/// [`AsRef`]: ../convert/trait.AsRef.html
+/// [`AsMut`]: ../convert/trait.AsMut.html
 #[unstable(feature = "fixed_size_array", issue = "27778")]
 pub unsafe trait FixedSizeArray<T> {
     /// Converts the array to immutable slice
index db3dde3fea6bd66948dceda916ba69c8622024a8..624b13d96472cfe1dad9ded9f9a134576666fba6 100644 (file)
@@ -427,7 +427,7 @@ pub trait TryInto<T>: Sized {
 /// - [`try_from`] is reflexive, which means that `TryFrom<T> for T`
 /// is implemented and cannot fail -- the associated `Error` type for
 /// calling `T::try_from()` on a value of type `T` is [`Infallible`].
-/// When the [`!`] type is stablized [`Infallible`] and [`!`] will be
+/// When the [`!`] type is stabilized [`Infallible`] and [`!`] will be
 /// equivalent.
 ///
 /// `TryFrom<T>` can be implemented as follows:
index 8bd1601a362133899176df264d1a7373df31f706..593c01060ca49ae981ce21ceab6423055e85cf30 100644 (file)
 /// final value. This method does not block if the value is not ready. Instead,
 /// the current task is scheduled to be woken up when it's possible to make
 /// further progress by `poll`ing again. The `context` passed to the `poll`
-/// method can provide a `Waker`, which is a handle for waking up the current
+/// method can provide a [`Waker`], which is a handle for waking up the current
 /// task.
 ///
 /// When using a future, you generally won't call `poll` directly, but instead
 /// `.await` the value.
+///
+/// [`Waker`]: ../task/struct.Waker.html
 #[doc(spotlight)]
 #[must_use = "futures do nothing unless you `.await` or poll them"]
 #[stable(feature = "futures_api", since = "1.36.0")]
index db0a6eff8367d7666389babec72b89d709ac82f2..37cc71bff62b4e9fa42d4793f3229f7bab0aa718 100644 (file)
@@ -353,11 +353,15 @@ macro_rules! r#try {
 /// use std::fmt::Write as FmtWrite;
 /// use std::io::Write as IoWrite;
 ///
-/// let mut s = String::new();
-/// let mut v = Vec::new();
-/// write!(&mut s, "{} {}", "abc", 123).unwrap(); // uses fmt::Write::write_fmt
-/// write!(&mut v, "s = {:?}", s).unwrap(); // uses io::Write::write_fmt
-/// assert_eq!(v, b"s = \"abc 123\"");
+/// fn main() -> Result<(), Box<dyn std::error::Error>> {
+///     let mut s = String::new();
+///     let mut v = Vec::new();
+///
+///     write!(&mut s, "{} {}", "abc", 123)?; // uses fmt::Write::write_fmt
+///     write!(&mut v, "s = {:?}", s)?; // uses io::Write::write_fmt
+///     assert_eq!(v, b"s = \"abc 123\"");
+///     Ok(())
+/// }
 /// ```
 ///
 /// Note: This macro can be used in `no_std` setups as well.
@@ -399,14 +403,17 @@ macro_rules! write {
 /// # Examples
 ///
 /// ```
-/// use std::io::Write;
+/// use std::io::{Write, Result};
 ///
-/// let mut w = Vec::new();
-/// writeln!(&mut w).unwrap();
-/// writeln!(&mut w, "test").unwrap();
-/// writeln!(&mut w, "formatted {}", "arguments").unwrap();
+/// fn main() -> Result<()> {
+///     let mut w = Vec::new();
+///     writeln!(&mut w)?;
+///     writeln!(&mut w, "test")?;
+///     writeln!(&mut w, "formatted {}", "arguments")?;
 ///
-/// assert_eq!(&w[..], "\ntest\nformatted arguments\n".as_bytes());
+///     assert_eq!(&w[..], "\ntest\nformatted arguments\n".as_bytes());
+///     Ok(())
+/// }
 /// ```
 ///
 /// A module can import both `std::fmt::Write` and `std::io::Write` and call `write!` on objects
@@ -417,11 +424,15 @@ macro_rules! write {
 /// use std::fmt::Write as FmtWrite;
 /// use std::io::Write as IoWrite;
 ///
-/// let mut s = String::new();
-/// let mut v = Vec::new();
-/// writeln!(&mut s, "{} {}", "abc", 123).unwrap(); // uses fmt::Write::write_fmt
-/// writeln!(&mut v, "s = {:?}", s).unwrap(); // uses io::Write::write_fmt
-/// assert_eq!(v, b"s = \"abc 123\\n\"\n");
+/// fn main() -> Result<(), Box<dyn std::error::Error>> {
+///     let mut s = String::new();
+///     let mut v = Vec::new();
+///
+///     writeln!(&mut s, "{} {}", "abc", 123)?; // uses fmt::Write::write_fmt
+///     writeln!(&mut v, "s = {:?}", s)?; // uses io::Write::write_fmt
+///     assert_eq!(v, b"s = \"abc 123\\n\"\n");
+///     Ok(())
+/// }
 /// ```
 #[macro_export]
 #[stable(feature = "rust1", since = "1.0.0")]
index 2e88db8df11634f3ea30c78340a2d12fb2722137..64fdf504369f2a555335c87a837377e253b2e1ac 100644 (file)
@@ -434,7 +434,7 @@ pub unsafe fn assume_init(self) -> T {
     /// Reads the value from the `MaybeUninit<T>` container. The resulting `T` is subject
     /// to the usual drop handling.
     ///
-    /// Whenever possible, it is preferrable to use [`assume_init`] instead, which
+    /// Whenever possible, it is preferable to use [`assume_init`] instead, which
     /// prevents duplicating the content of the `MaybeUninit<T>`.
     ///
     /// # Safety
index a1f96905dc99b269b8eb2139caca613f9391d3f0..0ec4dd47b1ff017f8b0aaba6640caa9aceb2c95b 100644 (file)
@@ -1611,7 +1611,7 @@ pub unsafe fn copy_to_nonoverlapping(self, dest: *mut T, count: usize)
     /// The offset is expressed in number of `T` elements, and not bytes. The value returned can be
     /// used with the `add` method.
     ///
-    /// There are no guarantees whatsover that offsetting the pointer will not overflow or go
+    /// There are no guarantees whatsoever that offsetting the pointer will not overflow or go
     /// beyond the allocation that the pointer points into. It is up to the caller to ensure that
     /// the returned offset is correct in all terms other than alignment.
     ///
@@ -2412,7 +2412,7 @@ pub unsafe fn swap(self, with: *mut T)
     /// The offset is expressed in number of `T` elements, and not bytes. The value returned can be
     /// used with the `add` method.
     ///
-    /// There are no guarantees whatsover that offsetting the pointer will not overflow or go
+    /// There are no guarantees whatsoever that offsetting the pointer will not overflow or go
     /// beyond the allocation that the pointer points into. It is up to the caller to ensure that
     /// the returned offset is correct in all terms other than alignment.
     ///
index 3d57a89493e1ea7aaf0c09d7e186c6e82ac647fb..db724875b8aa390b16aaf4b3fe7ef722a1818054 100644 (file)
@@ -693,7 +693,7 @@ fn canonicalize_const_var(
         const_var: &'tcx ty::Const<'tcx>
     ) -> &'tcx ty::Const<'tcx> {
         let infcx = self.infcx.expect("encountered const-var without infcx");
-        let bound_to = infcx.resolve_const_var(const_var);
+        let bound_to = infcx.shallow_resolve(const_var);
         if bound_to != const_var {
             self.fold_const(bound_to)
         } else {
index 663acd67dcd839b147f5e4b3a7fc263a70e0a0af..e1d77a97c116068fd0c26828d486c03e40b47dc9 100644 (file)
@@ -1351,23 +1351,6 @@ pub fn probe_const_var(
         }
     }
 
-    pub fn resolve_const_var(
-        &self,
-        ct: &'tcx ty::Const<'tcx>
-    ) -> &'tcx ty::Const<'tcx> {
-        if let ty::Const { val: ConstValue::Infer(InferConst::Var(v)), .. } = ct {
-            self.const_unification_table
-                .borrow_mut()
-                .probe_value(*v)
-                .val
-                .known()
-                .map(|c| self.resolve_const_var(c))
-                .unwrap_or(ct)
-        } else {
-            ct
-        }
-    }
-
     pub fn fully_resolve<T: TypeFoldable<'tcx>>(&self, value: &T) -> FixupResult<'tcx, T> {
         /*!
          * Attempts to resolve all type/region/const variables in
@@ -1586,7 +1569,7 @@ pub fn inlined_shallow_resolve(&mut self, typ: Ty<'tcx>) -> Ty<'tcx> {
                 // it can be resolved to an int/float variable, which
                 // can then be recursively resolved, hence the
                 // recursion. Note though that we prevent type
-                // variables from unifyxing to other type variables
+                // variables from unifying to other type variables
                 // directly (though they may be embedded
                 // structurally), and we prevent cycles in any case,
                 // so this recursion should always be of very limited
@@ -1626,17 +1609,15 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
     }
 
     fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
-        match ct {
-            ty::Const { val: ConstValue::Infer(InferConst::Var(vid)), .. } => {
+        if let ty::Const { val: ConstValue::Infer(InferConst::Var(vid)), .. } = ct {
                 self.infcx.const_unification_table
                     .borrow_mut()
                     .probe_value(*vid)
                     .val
                     .known()
-                    .map(|c| self.fold_const(c))
                     .unwrap_or(ct)
-            }
-            _ => ct,
+        } else {
+            ct
         }
     }
 }
index 51b2d0272a59713c89ae2b6db91e6d0af73f2f92..ce04cca96e0f93b144c16f1aeb04503b5bbdd339 100644 (file)
@@ -235,17 +235,17 @@ pub fn read_c_str(
     {
         assert_eq!(ptr.offset.bytes() as usize as u64, ptr.offset.bytes());
         let offset = ptr.offset.bytes() as usize;
-        match self.bytes[offset..].iter().position(|&c| c == 0) {
+        Ok(match self.bytes[offset..].iter().position(|&c| c == 0) {
             Some(size) => {
                 let size_with_null = Size::from_bytes((size + 1) as u64);
                 // Go through `get_bytes` for checks and AllocationExtra hooks.
                 // We read the null, so we include it in the request, but we want it removed
                 // from the result, so we do subslicing.
-                Ok(&self.get_bytes(cx, ptr, size_with_null)?[..size])
+                &self.get_bytes(cx, ptr, size_with_null)?[..size]
             }
             // This includes the case where `offset` is out-of-bounds to begin with.
-            None => err!(UnterminatedCString(ptr.erase_tag())),
-        }
+            None => throw_unsup!(UnterminatedCString(ptr.erase_tag())),
+        })
     }
 
     /// Validates that `ptr.offset` and `ptr.offset + size` do not point to the middle of a
@@ -446,7 +446,7 @@ fn check_relocations(
         if self.relocations(cx, ptr, size).is_empty() {
             Ok(())
         } else {
-            err!(ReadPointerAsBytes)
+            throw_unsup!(ReadPointerAsBytes)
         }
     }
 
@@ -516,7 +516,7 @@ fn check_defined(&self, ptr: Pointer<Tag>, size: Size) -> InterpResult<'tcx> {
         self.undef_mask.is_range_defined(
             ptr.offset,
             ptr.offset + size,
-        ).or_else(|idx| err!(ReadUndefBytes(idx)))
+        ).or_else(|idx| throw_unsup!(ReadUndefBytes(idx)))
     }
 
     pub fn mark_definedness(
index 5309d5b039e9ebb05f03cfe4ea5742091b7cf65d..8d41b019c221a4719d578556a47fa74c9398dfcf 100644 (file)
@@ -138,10 +138,12 @@ fn struct_generic(
         lint_root: Option<hir::HirId>,
     ) -> Result<DiagnosticBuilder<'tcx>, ErrorHandled> {
         match self.error {
-            InterpError::Layout(LayoutError::Unknown(_)) |
-            InterpError::TooGeneric => return Err(ErrorHandled::TooGeneric),
-            InterpError::Layout(LayoutError::SizeOverflow(_)) |
-            InterpError::TypeckError => return Err(ErrorHandled::Reported),
+            err_inval!(Layout(LayoutError::Unknown(_))) |
+            err_inval!(TooGeneric) =>
+                return Err(ErrorHandled::TooGeneric),
+            err_inval!(Layout(LayoutError::SizeOverflow(_))) |
+            err_inval!(TypeckError) =>
+                return Err(ErrorHandled::Reported),
             _ => {},
         }
         trace!("reporting const eval failure at {:?}", self.span);
@@ -181,8 +183,8 @@ pub fn struct_error<'tcx>(tcx: TyCtxtAt<'tcx>, msg: &str) -> DiagnosticBuilder<'
 /// Packages the kind of error we got from the const code interpreter
 /// up with a Rust-level backtrace of where the error occured.
 /// Thsese should always be constructed by calling `.into()` on
-/// a `InterpError`. In `librustc_mir::interpret`, we have the `err!`
-/// macro for this.
+/// a `InterpError`. In `librustc_mir::interpret`, we have `throw_err_*`
+/// macros for this.
 #[derive(Debug, Clone)]
 pub struct InterpErrorInfo<'tcx> {
     pub kind: InterpError<'tcx>,
@@ -234,7 +236,7 @@ fn from(kind: InterpError<'tcx>) -> Self {
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
-pub enum PanicMessage<O> {
+pub enum PanicInfo<O> {
     Panic {
         msg: Symbol,
         line: u32,
@@ -254,14 +256,14 @@ pub enum PanicMessage<O> {
 }
 
 /// Type for MIR `Assert` terminator error messages.
-pub type AssertMessage<'tcx> = PanicMessage<mir::Operand<'tcx>>;
+pub type AssertMessage<'tcx> = PanicInfo<mir::Operand<'tcx>>;
 
-impl<O> PanicMessage<O> {
+impl<O> PanicInfo<O> {
     /// Getting a description does not require `O` to be printable, and does not
     /// require allocation.
     /// The caller is expected to handle `Panic` and `BoundsCheck` separately.
     pub fn description(&self) -> &'static str {
-        use PanicMessage::*;
+        use PanicInfo::*;
         match self {
             Overflow(mir::BinOp::Add) =>
                 "attempt to add with overflow",
@@ -290,14 +292,14 @@ pub fn description(&self) -> &'static str {
             GeneratorResumedAfterPanic =>
                 "generator resumed after panicking",
             Panic { .. } | BoundsCheck { .. } =>
-                bug!("Unexpected PanicMessage"),
+                bug!("Unexpected PanicInfo"),
         }
     }
 }
 
-impl<O: fmt::Debug> fmt::Debug for PanicMessage<O> {
+impl<O: fmt::Debug> fmt::Debug for PanicInfo<O> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        use PanicMessage::*;
+        use PanicInfo::*;
         match self {
             Panic { ref msg, line, col, ref file } =>
                 write!(f, "the evaluated program panicked at '{}', {}:{}:{}", msg, file, line, col),
@@ -310,20 +312,64 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
-pub enum InterpError<'tcx> {
-    /// This variant is used by machines to signal their own errors that do not
-    /// match an existing variant.
-    MachineError(String),
+pub enum InvalidProgramInfo<'tcx> {
+    /// Resolution can fail if we are in a too generic context.
+    TooGeneric,
+    /// Cannot compute this constant because it depends on another one
+    /// which already produced an error.
+    ReferencedConstant,
+    /// Abort in case type errors are reached.
+    TypeckError,
+    /// An error occurred during layout computation.
+    Layout(layout::LayoutError<'tcx>),
+}
 
-    /// Not actually an interpreter error -- used to signal that execution has exited
-    /// with the given status code.  Used by Miri, but not by CTFE.
-    Exit(i32),
+impl fmt::Debug for InvalidProgramInfo<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        use InvalidProgramInfo::*;
+        match self {
+            TooGeneric =>
+                write!(f, "encountered overly generic constant"),
+            ReferencedConstant =>
+                write!(f, "referenced constant has errors"),
+            TypeckError =>
+                write!(f, "encountered constants with type errors, stopping evaluation"),
+            Layout(ref err) =>
+                write!(f, "rustc layout computation failed: {:?}", err),
+        }
+    }
+}
 
+#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
+pub enum UndefinedBehaviourInfo {
+    /// Handle cases which for which we do not have a fixed variant.
+    Ub(String),
+    /// Unreachable code was executed.
+    Unreachable,
+}
+
+impl fmt::Debug for UndefinedBehaviourInfo {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        use UndefinedBehaviourInfo::*;
+        match self {
+            Ub(ref msg) =>
+                write!(f, "{}", msg),
+            Unreachable =>
+                write!(f, "entered unreachable code"),
+        }
+    }
+}
+
+#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
+pub enum UnsupportedOpInfo<'tcx> {
+    /// Handle cases which for which we do not have a fixed variant.
+    Unimplemented(String),
+
+    // -- Everything below is not classified yet --
     FunctionAbiMismatch(Abi, Abi),
     FunctionArgMismatch(Ty<'tcx>, Ty<'tcx>),
     FunctionRetMismatch(Ty<'tcx>, Ty<'tcx>),
     FunctionArgCountMismatch,
-    NoMirFor(String),
     UnterminatedCString(Pointer),
     DanglingPointerDeref,
     DoubleFree,
@@ -344,12 +390,17 @@ pub enum InterpError<'tcx> {
     ReadUndefBytes(Size),
     DeadLocal,
     InvalidBoolOp(mir::BinOp),
-    Unimplemented(String),
+    InlineAsm,
+    UnimplementedTraitSelection,
+    CalledClosureAsFunction,
+    NoMirFor(String),
+    /// This variant is used by machines to signal their own errors that do not
+    /// match an existing variant.
+    MachineError(String),
     DerefFunctionPointer,
     ExecuteMemory,
     Intrinsic(String),
     InvalidChar(u128),
-    StackFrameLimitReached,
     OutOfTls,
     TlsOutOfBounds,
     AbiViolation(String),
@@ -358,49 +409,26 @@ pub enum InterpError<'tcx> {
         has: Align,
     },
     ValidationFailure(String),
-    CalledClosureAsFunction,
     VtableForArgumentlessMethod,
     ModifiedConstantMemory,
     ModifiedStatic,
     AssumptionNotHeld,
-    InlineAsm,
     TypeNotPrimitive(Ty<'tcx>),
     ReallocatedWrongMemoryKind(String, String),
     DeallocatedWrongMemoryKind(String, String),
     ReallocateNonBasePtr,
     DeallocateNonBasePtr,
     IncorrectAllocationInformation(Size, Size, Align, Align),
-    Layout(layout::LayoutError<'tcx>),
     HeapAllocZeroBytes,
     HeapAllocNonPowerOfTwoAlignment(u64),
-    Unreachable,
-    Panic(PanicMessage<u64>),
     ReadFromReturnPointer,
     PathNotFound(Vec<String>),
-    UnimplementedTraitSelection,
-    /// Abort in case type errors are reached
-    TypeckError,
-    /// Resolution can fail if we are in a too generic context
-    TooGeneric,
-    /// Cannot compute this constant because it depends on another one
-    /// which already produced an error
-    ReferencedConstant,
-    InfiniteLoop,
-}
-
-pub type InterpResult<'tcx, T = ()> = Result<T, InterpErrorInfo<'tcx>>;
-
-impl fmt::Display for InterpError<'_> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        // Forward `Display` to `Debug`
-        write!(f, "{:?}", self)
-    }
 }
 
-impl fmt::Debug for InterpError<'_> {
+impl fmt::Debug for UnsupportedOpInfo<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        use InterpError::*;
-        match *self {
+        use UnsupportedOpInfo::*;
+        match self {
             PointerOutOfBounds { ptr, msg, allocation_size } => {
                 write!(f, "{} failed: pointer must be in-bounds at offset {}, \
                           but is outside bounds of allocation {} which has size {}",
@@ -434,8 +462,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                       has.bytes(), required.bytes()),
             TypeNotPrimitive(ty) =>
                 write!(f, "expected primitive type, got {}", ty),
-            Layout(ref err) =>
-                write!(f, "rustc layout computation failed: {:?}", err),
             PathNotFound(ref path) =>
                 write!(f, "Cannot find path {:?}", path),
             IncorrectAllocationInformation(size, size2, align, align2) =>
@@ -444,8 +470,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                     size.bytes(), align.bytes(), size2.bytes(), align2.bytes()),
             InvalidDiscriminant(val) =>
                 write!(f, "encountered invalid enum discriminant {}", val),
-            Exit(code) =>
-                write!(f, "exited with status code {}", code),
             InvalidMemoryAccess =>
                 write!(f, "tried to access memory through an invalid pointer"),
             DanglingPointerDeref =>
@@ -474,8 +498,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                 write!(f, "tried to dereference a function pointer"),
             ExecuteMemory =>
                 write!(f, "tried to treat a memory pointer as a function pointer"),
-            StackFrameLimitReached =>
-                write!(f, "reached the configured maximum number of stack frames"),
             OutOfTls =>
                 write!(f, "reached the maximum number of representable TLS keys"),
             TlsOutOfBounds =>
@@ -501,21 +523,10 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                     existing object"),
             HeapAllocZeroBytes =>
                 write!(f, "tried to re-, de- or allocate zero bytes on the heap"),
-            Unreachable =>
-                write!(f, "entered unreachable code"),
             ReadFromReturnPointer =>
                 write!(f, "tried to read from the return pointer"),
             UnimplementedTraitSelection =>
                 write!(f, "there were unresolved type arguments during trait selection"),
-            TypeckError =>
-                write!(f, "encountered constants with type errors, stopping evaluation"),
-            TooGeneric =>
-                write!(f, "encountered overly generic constant"),
-            ReferencedConstant =>
-                write!(f, "referenced constant has errors"),
-            InfiniteLoop =>
-                write!(f, "duplicate interpreter state observed here, const evaluation will never \
-                    terminate"),
             InvalidBoolOp(_) =>
                 write!(f, "invalid boolean operation"),
             UnterminatedCString(_) =>
@@ -531,8 +542,75 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
             AbiViolation(ref msg) |
             Intrinsic(ref msg) =>
                 write!(f, "{}", msg),
+        }
+    }
+}
+
+#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
+pub enum ResourceExhaustionInfo {
+    /// The stack grew too big.
+    StackFrameLimitReached,
+    /// The program ran into an infinite loop.
+    InfiniteLoop,
+}
+
+impl fmt::Debug for ResourceExhaustionInfo {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        use ResourceExhaustionInfo::*;
+        match self {
+            StackFrameLimitReached =>
+                write!(f, "reached the configured maximum number of stack frames"),
+            InfiniteLoop =>
+                write!(f, "duplicate interpreter state observed here, const evaluation will never \
+                    terminate"),
+        }
+    }
+}
+
+#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
+pub enum InterpError<'tcx> {
+    /// The program panicked.
+    Panic(PanicInfo<u64>),
+    /// The program caused undefined behavior.
+    UndefinedBehaviour(UndefinedBehaviourInfo),
+    /// The program did something the interpreter does not support (some of these *might* be UB
+    /// but the interpreter is not sure).
+    Unsupported(UnsupportedOpInfo<'tcx>),
+    /// The program was invalid (ill-typed, not sufficiently monomorphized, ...).
+    InvalidProgram(InvalidProgramInfo<'tcx>),
+    /// The program exhausted the interpreter's resources (stack/heap too big,
+    /// execution takes too long, ..).
+    ResourceExhaustion(ResourceExhaustionInfo),
+    /// Not actually an interpreter error -- used to signal that execution has exited
+    /// with the given status code.  Used by Miri, but not by CTFE.
+    Exit(i32),
+}
+
+pub type InterpResult<'tcx, T = ()> = Result<T, InterpErrorInfo<'tcx>>;
+
+impl fmt::Display for InterpError<'_> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        // Forward `Display` to `Debug`
+        write!(f, "{:?}", self)
+    }
+}
+
+impl fmt::Debug for InterpError<'_> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        use InterpError::*;
+        match *self {
+            Unsupported(ref msg) =>
+                write!(f, "{:?}", msg),
+            InvalidProgram(ref msg) =>
+                write!(f, "{:?}", msg),
+            UndefinedBehaviour(ref msg) =>
+                write!(f, "{:?}", msg),
+            ResourceExhaustion(ref msg) =>
+                write!(f, "{:?}", msg),
             Panic(ref msg) =>
                 write!(f, "{:?}", msg),
+            Exit(code) =>
+                write!(f, "exited with status code {}", code),
         }
     }
 }
index 121b6ac0ac88c66f7350fa3578acf16118ddf94a..723a30792fddc0f7a7d0c3ac00ffdd8e5d324b47 100644 (file)
@@ -1,8 +1,73 @@
 //! An interpreter for MIR used in CTFE and by miri
 
 #[macro_export]
-macro_rules! err {
-    ($($tt:tt)*) => { Err($crate::mir::interpret::InterpError::$($tt)*.into()) };
+macro_rules! err_unsup {
+    ($($tt:tt)*) => {
+        $crate::mir::interpret::InterpError::Unsupported(
+            $crate::mir::interpret::UnsupportedOpInfo::$($tt)*
+        )
+    };
+}
+
+#[macro_export]
+macro_rules! err_inval {
+    ($($tt:tt)*) => {
+        $crate::mir::interpret::InterpError::InvalidProgram(
+            $crate::mir::interpret::InvalidProgramInfo::$($tt)*
+        )
+    };
+}
+
+#[macro_export]
+macro_rules! err_ub {
+    ($($tt:tt)*) => {
+        $crate::mir::interpret::InterpError::UndefinedBehaviour(
+            $crate::mir::interpret::UndefinedBehaviourInfo::$($tt)*
+        )
+    };
+}
+
+#[macro_export]
+macro_rules! err_panic {
+    ($($tt:tt)*) => {
+        $crate::mir::interpret::InterpError::Panic(
+            $crate::mir::interpret::PanicInfo::$($tt)*
+        )
+    };
+}
+
+#[macro_export]
+macro_rules! err_exhaust {
+    ($($tt:tt)*) => {
+        $crate::mir::interpret::InterpError::ResourceExhaustion(
+            $crate::mir::interpret::ResourceExhaustionInfo::$($tt)*
+        )
+    };
+}
+
+#[macro_export]
+macro_rules! throw_unsup {
+    ($($tt:tt)*) => { return Err(err_unsup!($($tt)*).into()) };
+}
+
+#[macro_export]
+macro_rules! throw_inval {
+    ($($tt:tt)*) => { return Err(err_inval!($($tt)*).into()) };
+}
+
+#[macro_export]
+macro_rules! throw_ub {
+    ($($tt:tt)*) => { return Err(err_ub!($($tt)*).into()) };
+}
+
+#[macro_export]
+macro_rules! throw_panic {
+    ($($tt:tt)*) => { return Err(err_panic!($($tt)*).into()) };
+}
+
+#[macro_export]
+macro_rules! throw_exhaust {
+    ($($tt:tt)*) => { return Err(err_exhaust!($($tt)*).into()) };
 }
 
 mod error;
@@ -12,7 +77,8 @@ macro_rules! err {
 
 pub use self::error::{
     InterpErrorInfo, InterpResult, InterpError, AssertMessage, ConstEvalErr, struct_error,
-    FrameInfo, ConstEvalRawResult, ConstEvalResult, ErrorHandled, PanicMessage
+    FrameInfo, ConstEvalRawResult, ConstEvalResult, ErrorHandled, PanicInfo, UnsupportedOpInfo,
+    InvalidProgramInfo, ResourceExhaustionInfo, UndefinedBehaviourInfo,
 };
 
 pub use self::value::{Scalar, ScalarMaybeUndef, RawConst, ConstValue};
index 0e3b8459115e30e96c325fc62adc720eac402a29..0a9985133799498cbe6c5734e2bff8d8fa68d8dd 100644 (file)
@@ -4,9 +4,7 @@
 use crate::ty::layout::{self, HasDataLayout, Size};
 use rustc_macros::HashStable;
 
-use super::{
-    AllocId, InterpResult, PanicMessage
-};
+use super::{AllocId, InterpResult};
 
 /// Used by `check_in_alloc` to indicate context of check
 #[derive(Debug, Copy, Clone, RustcEncodable, RustcDecodable, HashStable)]
@@ -76,13 +74,13 @@ fn overflowing_signed_offset(&self, val: u64, i: i128) -> (u64, bool) {
     #[inline]
     fn offset<'tcx>(&self, val: u64, i: u64) -> InterpResult<'tcx, u64> {
         let (res, over) = self.overflowing_offset(val, i);
-        if over { err!(Panic(PanicMessage::Overflow(mir::BinOp::Add))) } else { Ok(res) }
+        if over { throw_panic!(Overflow(mir::BinOp::Add)) } else { Ok(res) }
     }
 
     #[inline]
     fn signed_offset<'tcx>(&self, val: u64, i: i64) -> InterpResult<'tcx, u64> {
         let (res, over) = self.overflowing_signed_offset(val, i128::from(i));
-        if over { err!(Panic(PanicMessage::Overflow(mir::BinOp::Add))) } else { Ok(res) }
+        if over { throw_panic!(Overflow(mir::BinOp::Add)) } else { Ok(res) }
     }
 }
 
@@ -198,11 +196,7 @@ pub fn check_in_alloc(
         msg: CheckInAllocMsg,
     ) -> InterpResult<'tcx, ()> {
         if self.offset > allocation_size {
-            err!(PointerOutOfBounds {
-                ptr: self.erase_tag(),
-                msg,
-                allocation_size,
-            })
+            throw_unsup!(PointerOutOfBounds { ptr: self.erase_tag(), msg, allocation_size })
         } else {
             Ok(())
         }
index 4a59d845b3b42eebf76cf722e7e642d200126f68..607bcea7fe80109a224c57dd1b235d4e60f3b4f8 100644 (file)
@@ -360,7 +360,7 @@ pub fn to_bits(self, target_size: Size) -> InterpResult<'tcx, u128> {
                 Scalar::check_data(data, size);
                 Ok(data)
             }
-            Scalar::Ptr(_) => err!(ReadPointerAsBytes),
+            Scalar::Ptr(_) => throw_unsup!(ReadPointerAsBytes),
         }
     }
 
@@ -373,8 +373,8 @@ pub fn assert_bits(self, target_size: Size) -> u128 {
     #[inline]
     pub fn to_ptr(self) -> InterpResult<'tcx, Pointer<Tag>> {
         match self {
-            Scalar::Raw { data: 0, .. } => err!(InvalidNullPointerUsage),
-            Scalar::Raw { .. } => err!(ReadBytesAsPointer),
+            Scalar::Raw { data: 0, .. } => throw_unsup!(InvalidNullPointerUsage),
+            Scalar::Raw { .. } => throw_unsup!(ReadBytesAsPointer),
             Scalar::Ptr(p) => Ok(p),
         }
     }
@@ -406,7 +406,7 @@ pub fn to_bool(self) -> InterpResult<'tcx, bool> {
         match self {
             Scalar::Raw { data: 0, size: 1 } => Ok(false),
             Scalar::Raw { data: 1, size: 1 } => Ok(true),
-            _ => err!(InvalidBool),
+            _ => throw_unsup!(InvalidBool),
         }
     }
 
@@ -414,7 +414,7 @@ pub fn to_char(self) -> InterpResult<'tcx, char> {
         let val = self.to_u32()?;
         match ::std::char::from_u32(val) {
             Some(c) => Ok(c),
-            None => err!(InvalidChar(val as u128)),
+            None => throw_unsup!(InvalidChar(val as u128)),
         }
     }
 
@@ -537,7 +537,7 @@ pub fn erase_tag(self) -> ScalarMaybeUndef
     pub fn not_undef(self) -> InterpResult<'static, Scalar<Tag>> {
         match self {
             ScalarMaybeUndef::Scalar(scalar) => Ok(scalar),
-            ScalarMaybeUndef::Undef => err!(ReadUndefBytes(Size::from_bytes(0))),
+            ScalarMaybeUndef::Undef => throw_unsup!(ReadUndefBytes(Size::from_bytes(0))),
         }
     }
 
index 50f16858c0486835a750f9534b0c271c85dd8689..1e2ec08301cf91f544aa4515dd818de05ce13ede 100644 (file)
@@ -7,7 +7,7 @@
 use crate::hir::def::{CtorKind, Namespace};
 use crate::hir::def_id::DefId;
 use crate::hir::{self, InlineAsm as HirInlineAsm};
-use crate::mir::interpret::{ConstValue, PanicMessage, Scalar};
+use crate::mir::interpret::{ConstValue, PanicInfo, Scalar};
 use crate::mir::visit::MirVisitable;
 use crate::ty::adjustment::PointerCast;
 use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
@@ -3152,7 +3152,7 @@ fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
                 }
             }
             Assert { ref cond, expected, ref msg, target, cleanup } => {
-                use PanicMessage::*;
+                use PanicInfo::*;
                 let msg = match msg {
                     BoundsCheck { ref len, ref index } =>
                         BoundsCheck {
@@ -3200,7 +3200,7 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
             }
             Assert { ref cond, ref msg, .. } => {
                 if cond.visit_with(visitor) {
-                    use PanicMessage::*;
+                    use PanicInfo::*;
                     match msg {
                         BoundsCheck { ref len, ref index } =>
                             len.visit_with(visitor) || index.visit_with(visitor),
index 7562981f94f61aab897ad68a74b17c7b37c09669..ee4ecb6762c96a674267956c295876663027d92b 100644 (file)
@@ -514,7 +514,7 @@ fn super_terminator_kind(&mut self,
             fn super_assert_message(&mut self,
                                     msg: & $($mutability)? AssertMessage<'tcx>,
                                     location: Location) {
-                use crate::mir::interpret::PanicMessage::*;
+                use crate::mir::interpret::PanicInfo::*;
                 match msg {
                     BoundsCheck { len, index } => {
                         self.visit_operand(len, location);
index 798a25fe7b1bc0d7be18935c9b0f21b574929bf3..2486f29ab0f222606d5814d299ecff8df1468a48 100644 (file)
@@ -167,7 +167,7 @@ struct TraitObligationStack<'prev, 'tcx> {
     /// ok on the premise that if `A: AutoTrait` held, but we indeed
     /// encountered a problem (later on) with `A: AutoTrait. So we
     /// currently set a flag on the stack node for `B: AutoTrait` (as
-    /// well as the second instance of `A: AutoTrait`) to supress
+    /// well as the second instance of `A: AutoTrait`) to suppress
     /// caching.
     ///
     /// This is a simple, targeted fix. A more-performant fix requires
@@ -1105,7 +1105,7 @@ fn evaluate_stack<'o>(
     ///
     /// - is a defaulted trait,
     /// - it also appears in the backtrace at some position `X`,
-    /// - all the predicates at positions `X..` between `X` an the top are
+    /// - all the predicates at positions `X..` between `X` and the top are
     ///   also defaulted traits.
     pub fn coinductive_match<I>(&mut self, cycle: I) -> bool
     where
index a6bfc2dee613b0ce04bb8e997f1cd4550cd390ff..ca54f63b83afe0c2acc30e6f38162a9cbf7dedb8 100644 (file)
@@ -594,13 +594,11 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
                 ty: a.ty,
             }))
         }
-        (ConstValue::ByRef { .. }, _) => {
-            bug!(
-                "non-Scalar ConstValue encountered in super_relate_consts {:?} {:?}",
-                a,
-                b,
-            );
-        }
+
+        // FIXME(const_generics): we should either handle `Scalar::Ptr` or add a comment
+        // saying that we're not handling it intentionally.
+
+        // FIXME(const_generics): handle `ConstValue::ByRef` and `ConstValue::Slice`.
 
         // FIXME(const_generics): this is wrong, as it is a projection
         (ConstValue::Unevaluated(a_def_id, a_substs),
index 18611c3e167d22893eaeed234cf7f847eb6cd602..006ebcbdec6727797112984932f2ebc0e8430d52 100644 (file)
@@ -2,7 +2,7 @@
 use rustc::ty::{self, Ty, TypeFoldable, Instance};
 use rustc::ty::layout::{self, LayoutOf, HasTyCtxt, FnTypeExt};
 use rustc::mir::{self, Place, PlaceBase, Static, StaticKind};
-use rustc::mir::interpret::PanicMessage;
+use rustc::mir::interpret::PanicInfo;
 use rustc_target::abi::call::{ArgType, FnType, PassMode, IgnoreMode};
 use rustc_target::spec::abi::Abi;
 use crate::base;
@@ -368,7 +368,7 @@ fn codegen_assert_terminator<'b>(
         // checked operation, just a comparison with the minimum
         // value, so we have to check for the assert message.
         if !bx.check_overflow() {
-            if let PanicMessage::OverflowNeg = *msg {
+            if let PanicInfo::OverflowNeg = *msg {
                 const_cond = Some(expected);
             }
         }
@@ -403,7 +403,7 @@ fn codegen_assert_terminator<'b>(
 
         // Put together the arguments to the panic entry point.
         let (lang_item, args) = match msg {
-            PanicMessage::BoundsCheck { ref len, ref index } => {
+            PanicInfo::BoundsCheck { ref len, ref index } => {
                 let len = self.codegen_operand(&mut bx, len).immediate();
                 let index = self.codegen_operand(&mut bx, index).immediate();
 
index e53e5734cc5f7683f204dda021d3e45855736e0e..9f22d7c51df6e6210fddc759e2db580ba4e6ee57 100644 (file)
@@ -733,8 +733,8 @@ fn visit_terminator_entry(
                 cleanup: _,
             } => {
                 self.consume_operand(loc, (cond, span), flow_state);
-                use rustc::mir::interpret::PanicMessage;
-                if let PanicMessage::BoundsCheck { ref len, ref index } = *msg {
+                use rustc::mir::interpret::PanicInfo;
+                if let PanicInfo::BoundsCheck { ref len, ref index } = *msg {
                     self.consume_operand(loc, (len, span), flow_state);
                     self.consume_operand(loc, (index, span), flow_state);
                 }
index aa9e68bd7de4412bf91e7e5cb0b2a291bbf40f35..631a81421131c334290d06af2ef8ddcb157f5b2e 100644 (file)
@@ -207,8 +207,8 @@ fn visit_terminator_kind(
                 cleanup: _,
             } => {
                 self.consume_operand(location, cond);
-                use rustc::mir::interpret::PanicMessage;
-                if let PanicMessage::BoundsCheck { ref len, ref index } = *msg {
+                use rustc::mir::interpret::PanicInfo;
+                if let PanicInfo::BoundsCheck { ref len, ref index } = *msg {
                     self.consume_operand(location, len);
                     self.consume_operand(location, index);
                 }
index 50c0640f885f2f25a1102812bee95aa6ce1cf67b..f10d505fe89830ca6e46e74371268c6f3eca1d2e 100644 (file)
@@ -26,7 +26,7 @@
 use rustc::infer::outlives::env::RegionBoundPairs;
 use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionVariableOrigin};
 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use rustc::mir::interpret::{ConstValue, PanicMessage};
+use rustc::mir::interpret::{ConstValue, PanicInfo};
 use rustc::mir::tcx::PlaceTy;
 use rustc::mir::visit::{PlaceContext, Visitor, NonMutatingUseContext};
 use rustc::mir::*;
@@ -1632,7 +1632,7 @@ fn check_terminator(
                     span_mirbug!(self, term, "bad Assert ({:?}, not bool", cond_ty);
                 }
 
-                if let PanicMessage::BoundsCheck { ref len, ref index } = *msg {
+                if let PanicInfo::BoundsCheck { ref len, ref index } = *msg {
                     if len.ty(body, tcx) != tcx.types.usize {
                         span_mirbug!(self, len, "bounds-check length non-usize {:?}", len)
                     }
index 7a428a2ec9f3626d149714db264af8bf077c7e0b..7005f274e0e7def29f39b88d373595e4b1751c67 100644 (file)
@@ -4,7 +4,7 @@
 use crate::build::ForGuard::{OutsideGuard, RefWithinGuard};
 use crate::build::{BlockAnd, BlockAndExtension, Builder};
 use crate::hair::*;
-use rustc::mir::interpret::{PanicMessage::BoundsCheck};
+use rustc::mir::interpret::{PanicInfo::BoundsCheck};
 use rustc::mir::*;
 use rustc::ty::{CanonicalUserTypeAnnotation, Variance};
 
index 92daf06e6f8fefea4dbf21dba879996b2d431c74..ec061e74535778d7865c0f2b18700f9ed73e0982 100644 (file)
@@ -7,7 +7,7 @@
 use crate::build::{BlockAnd, BlockAndExtension, Builder};
 use crate::hair::*;
 use rustc::middle::region;
-use rustc::mir::interpret::PanicMessage;
+use rustc::mir::interpret::PanicInfo;
 use rustc::mir::*;
 use rustc::ty::{self, CanonicalUserTypeAnnotation, Ty, UpvarSubsts};
 use syntax_pos::Span;
@@ -101,7 +101,7 @@ fn expr_as_rvalue(
                         block,
                         Operand::Move(is_min),
                         false,
-                        PanicMessage::OverflowNeg,
+                        PanicInfo::OverflowNeg,
                         expr_span,
                     );
                 }
@@ -401,7 +401,7 @@ pub fn build_binary_op(
             let val = result_value.clone().field(val_fld, ty);
             let of = result_value.field(of_fld, bool_ty);
 
-            let err = PanicMessage::Overflow(op);
+            let err = PanicInfo::Overflow(op);
 
             block = self.assert(block, Operand::Move(of), false, err, span);
 
@@ -412,11 +412,11 @@ pub fn build_binary_op(
                 // and 2. there are two possible failure cases, divide-by-zero and overflow.
 
                 let zero_err = if op == BinOp::Div {
-                    PanicMessage::DivisionByZero
+                    PanicInfo::DivisionByZero
                 } else {
-                    PanicMessage::RemainderByZero
+                    PanicInfo::RemainderByZero
                 };
-                let overflow_err = PanicMessage::Overflow(op);
+                let overflow_err = PanicInfo::Overflow(op);
 
                 // Check for / 0
                 let is_zero = self.temp(bool_ty, span);
index 37d4c5b2f09ce95fbf72e592127f5c6e8f54bf10..1b92e4992ffb1b90d316afcc99852a25a677de0f 100644 (file)
@@ -22,7 +22,7 @@
 use crate::interpret::{self,
     PlaceTy, MPlaceTy, OpTy, ImmTy, Immediate, Scalar,
     RawConst, ConstValue,
-    InterpResult, InterpErrorInfo, InterpError, GlobalId, InterpCx, StackPopCleanup,
+    InterpResult, InterpErrorInfo, GlobalId, InterpCx, StackPopCleanup,
     Allocation, AllocId, MemoryKind,
     snapshot, RefTracking, intern_const_alloc_recursive,
 };
@@ -183,7 +183,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
 
 impl<'tcx> Into<InterpErrorInfo<'tcx>> for ConstEvalError {
     fn into(self) -> InterpErrorInfo<'tcx> {
-        InterpError::MachineError(self.to_string()).into()
+        err_unsup!(MachineError(self.to_string())).into()
     }
 }
 
@@ -352,7 +352,7 @@ fn find_fn(
                     ecx.goto_block(ret)?; // fully evaluated and done
                     Ok(None)
                 } else {
-                    err!(MachineError(format!("calling non-const function `{}`", instance)))
+                    throw_unsup!(MachineError(format!("calling non-const function `{}`", instance)))
                 };
             }
         }
@@ -360,7 +360,7 @@ fn find_fn(
         Ok(Some(match ecx.load_mir(instance.def) {
             Ok(body) => body,
             Err(err) => {
-                if let InterpError::NoMirFor(ref path) = err.kind {
+                if let err_unsup!(NoMirFor(ref path)) = err.kind {
                     return Err(
                         ConstEvalError::NeedsRfc(format!("calling extern function `{}`", path))
                             .into(),
@@ -412,7 +412,7 @@ fn find_foreign_static(
         _tcx: TyCtxt<'tcx>,
         _def_id: DefId,
     ) -> InterpResult<'tcx, Cow<'tcx, Allocation<Self::PointerTag>>> {
-        err!(ReadForeignStatic)
+        throw_unsup!(ReadForeignStatic)
     }
 
     #[inline(always)]
@@ -698,7 +698,7 @@ pub fn const_eval_raw_provider<'tcx>(
                 // any other kind of error will be reported to the user as a deny-by-default lint
                 _ => if let Some(p) = cid.promoted {
                     let span = tcx.promoted_mir(def_id)[p].span;
-                    if let InterpError::ReferencedConstant = err.error {
+                    if let err_inval!(ReferencedConstant) = err.error {
                         err.report_as_error(
                             tcx.at(span),
                             "evaluation of constant expression failed",
index 980697360eb7574e95778f7dca4374f89323f723..a481a3b37b7177e4b4876ca05f2106be9cdd5716 100644 (file)
@@ -7,7 +7,7 @@
 use rustc_apfloat::ieee::{Single, Double};
 use rustc_apfloat::{Float, FloatConvert};
 use rustc::mir::interpret::{
-    Scalar, InterpResult, Pointer, PointerArithmetic, InterpError,
+    Scalar, InterpResult, Pointer, PointerArithmetic,
 };
 use rustc::mir::CastKind;
 
@@ -80,13 +80,13 @@ pub fn cast(
                         if self.tcx.has_attr(def_id, sym::rustc_args_required_const) {
                             bug!("reifying a fn ptr that requires const arguments");
                         }
-                        let instance: InterpResult<'tcx, _> = ty::Instance::resolve(
+                        let instance = ty::Instance::resolve(
                             *self.tcx,
                             self.param_env,
                             def_id,
                             substs,
-                        ).ok_or_else(|| InterpError::TooGeneric.into());
-                        let fn_ptr = self.memory.create_fn_alloc(FnVal::Instance(instance?));
+                        ).ok_or_else(|| err_inval!(TooGeneric))?;
+                        let fn_ptr = self.memory.create_fn_alloc(FnVal::Instance(instance));
                         self.write_scalar(Scalar::Ptr(fn_ptr.into()), dest)?;
                     }
                     _ => bug!("reify fn pointer on {:?}", src.layout.ty),
@@ -199,7 +199,7 @@ fn cast_from_int(
             },
 
             // Casts to bool are not permitted by rustc, no need to handle them here.
-            _ => err!(Unimplemented(format!("int to {:?} cast", dest_layout.ty))),
+            _ => throw_unsup!(Unimplemented(format!("int to {:?} cast", dest_layout.ty))),
         }
     }
 
index 007ec8cb2db5c50ff070f73bc21511bd2bdf4d8a..f10d7fb96511601cddbb4f79e60ec9fc0cbe3c26 100644 (file)
@@ -16,8 +16,7 @@
 use rustc::mir::interpret::{
     ErrorHandled,
     GlobalId, Scalar, Pointer, FrameInfo, AllocId,
-    InterpResult, InterpError,
-    truncate, sign_extend,
+    InterpResult, truncate, sign_extend,
 };
 use rustc_data_structures::fx::FxHashMap;
 
@@ -135,7 +134,7 @@ pub enum LocalValue<Tag=(), Id=AllocId> {
 impl<'tcx, Tag: Copy + 'static> LocalState<'tcx, Tag> {
     pub fn access(&self) -> InterpResult<'tcx, Operand<Tag>> {
         match self.value {
-            LocalValue::Dead => err!(DeadLocal),
+            LocalValue::Dead => throw_unsup!(DeadLocal),
             LocalValue::Uninitialized =>
                 bug!("The type checker should prevent reading from a never-written local"),
             LocalValue::Live(val) => Ok(val),
@@ -148,7 +147,7 @@ pub fn access_mut(
         &mut self,
     ) -> InterpResult<'tcx, Result<&mut LocalValue<Tag>, MemPlace<Tag>>> {
         match self.value {
-            LocalValue::Dead => err!(DeadLocal),
+            LocalValue::Dead => throw_unsup!(DeadLocal),
             LocalValue::Live(Operand::Indirect(mplace)) => Ok(Err(mplace)),
             ref mut local @ LocalValue::Live(Operand::Immediate(_)) |
             ref mut local @ LocalValue::Uninitialized => {
@@ -190,8 +189,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> LayoutOf for InterpCx<'mir, 'tcx, M> {
 
     #[inline]
     fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyLayout {
-        self.tcx.layout_of(self.param_env.and(ty))
-            .map_err(|layout| InterpError::Layout(layout).into())
+        self.tcx
+            .layout_of(self.param_env.and(ty))
+            .map_err(|layout| err_inval!(Layout(layout)).into())
     }
 }
 
@@ -302,7 +302,7 @@ pub(super) fn subst_and_normalize_erasing_regions<T: TypeFoldable<'tcx>>(
                 &substs,
             )),
             None => if substs.needs_subst() {
-                err!(TooGeneric).into()
+                throw_inval!(TooGeneric)
             } else {
                 Ok(substs)
             },
@@ -323,7 +323,7 @@ pub(super) fn resolve(
             self.param_env,
             def_id,
             substs,
-        ).ok_or_else(|| InterpError::TooGeneric.into())
+        ).ok_or_else(|| err_inval!(TooGeneric).into())
     }
 
     pub fn load_mir(
@@ -336,14 +336,14 @@ pub fn load_mir(
             && self.tcx.has_typeck_tables(did)
             && self.tcx.typeck_tables_of(did).tainted_by_errors
         {
-            return err!(TypeckError);
+            throw_inval!(TypeckError)
         }
         trace!("load mir {:?}", instance);
         match instance {
             ty::InstanceDef::Item(def_id) => if self.tcx.is_mir_available(did) {
                 Ok(self.tcx.optimized_mir(did))
             } else {
-                err!(NoMirFor(self.tcx.def_path_str(def_id)))
+                throw_unsup!(NoMirFor(self.tcx.def_path_str(def_id)))
             },
             _ => Ok(self.tcx.instance_mir(instance)),
         }
@@ -356,7 +356,7 @@ pub(super) fn monomorphize<T: TypeFoldable<'tcx> + Subst<'tcx>>(
         match self.stack.last() {
             Some(frame) => Ok(self.monomorphize_with_substs(t, frame.instance.substs)?),
             None => if t.needs_subst() {
-                err!(TooGeneric).into()
+                throw_inval!(TooGeneric)
             } else {
                 Ok(t)
             },
@@ -373,7 +373,7 @@ fn monomorphize_with_substs<T: TypeFoldable<'tcx> + Subst<'tcx>>(
         let substituted = t.subst(*self.tcx, substs);
 
         if substituted.needs_subst() {
-            return err!(TooGeneric);
+            throw_inval!(TooGeneric)
         }
 
         Ok(self.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), substituted))
@@ -572,7 +572,7 @@ pub fn push_stack_frame(
         info!("ENTERING({}) {}", self.cur_frame(), self.frame().instance);
 
         if self.stack.len() > self.tcx.sess.const_eval_stack_frame_limit {
-            err!(StackFrameLimitReached)
+            throw_exhaust!(StackFrameLimitReached)
         } else {
             Ok(())
         }
@@ -620,7 +620,7 @@ pub(super) fn pop_stack_frame(&mut self) -> InterpResult<'tcx> {
             }
         } else {
             // Uh, that shouldn't happen... the function did not intend to return
-            return err!(Unreachable);
+            throw_ub!(Unreachable)
         }
         // Jump to new block -- *after* validation so that the spans make more sense.
         match frame.return_to_block {
@@ -694,8 +694,10 @@ pub fn const_eval_raw(
         // `Memory::get_static_alloc` which has to use `const_eval_raw` to avoid cycles.
         let val = self.tcx.const_eval_raw(param_env.and(gid)).map_err(|err| {
             match err {
-                ErrorHandled::Reported => InterpError::ReferencedConstant,
-                ErrorHandled::TooGeneric => InterpError::TooGeneric,
+                ErrorHandled::Reported =>
+                    err_inval!(ReferencedConstant),
+                ErrorHandled::TooGeneric =>
+                    err_inval!(TooGeneric),
             }
         })?;
         self.raw_const_to_mplace(val)
index bcd36ac547c730525d2e0c5a13d7acee428362a5..e9bba7889119a2f6a532f1d5bb0476640f8e7988 100644 (file)
@@ -4,9 +4,7 @@
 //! memory, we need to extract all memory allocations to the global memory pool so they stay around.
 
 use rustc::ty::{Ty, TyCtxt, ParamEnv, self};
-use rustc::mir::interpret::{
-    InterpResult, ErrorHandled,
-};
+use rustc::mir::interpret::{InterpResult, ErrorHandled};
 use rustc::hir;
 use rustc::hir::def_id::DefId;
 use super::validity::RefTracking;
@@ -16,7 +14,7 @@
 use syntax_pos::Span;
 
 use super::{
-    ValueVisitor, MemoryKind, Pointer, AllocId, MPlaceTy, InterpError, Scalar,
+    ValueVisitor, MemoryKind, Pointer, AllocId, MPlaceTy, Scalar,
 };
 use crate::const_eval::{CompileTimeInterpreter, CompileTimeEvalContext};
 
@@ -293,7 +291,7 @@ pub fn intern_const_alloc_recursive(
         if let Err(error) = interned {
             // This can happen when e.g. the tag of an enum is not a valid discriminant. We do have
             // to read enum discriminants in order to find references in enum variant fields.
-            if let InterpError::ValidationFailure(_) = error.kind {
+            if let err_unsup!(ValidationFailure(_)) = error.kind {
                 let err = crate::const_eval::error_to_const_error(&ecx, error);
                 match err.struct_error(ecx.tcx, "it is undefined behavior to use this value") {
                     Ok(mut diag) => {
@@ -328,9 +326,7 @@ pub fn intern_const_alloc_recursive(
             }
         } else if ecx.memory().dead_alloc_map.contains_key(&alloc_id) {
             // dangling pointer
-            return err!(ValidationFailure(
-                "encountered dangling pointer in final constant".into(),
-            ))
+            throw_unsup!(ValidationFailure("encountered dangling pointer in final constant".into()))
         }
     }
     Ok(())
index 6a5b933e4a530fdb9cc276ccbb188d8a23624490..97866adcfa333ed75e35d8103aed46d6a6ac0d71 100644 (file)
@@ -6,9 +6,7 @@
 use rustc::ty;
 use rustc::ty::layout::{LayoutOf, Primitive, Size};
 use rustc::mir::BinOp;
-use rustc::mir::interpret::{
-    InterpResult, InterpError, Scalar, PanicMessage,
-};
+use rustc::mir::interpret::{InterpResult, Scalar};
 
 use super::{
     Machine, PlaceTy, OpTy, InterpCx, Immediate,
@@ -100,11 +98,11 @@ pub fn emulate_intrinsic(
                 let bits = self.read_scalar(args[0])?.to_bits(layout_of.size)?;
                 let kind = match layout_of.abi {
                     ty::layout::Abi::Scalar(ref scalar) => scalar.value,
-                    _ => Err(::rustc::mir::interpret::InterpError::TypeNotPrimitive(ty))?,
+                    _ => Err(err_unsup!(TypeNotPrimitive(ty)))?,
                 };
                 let out_val = if intrinsic_name.ends_with("_nonzero") {
                     if bits == 0 {
-                        return err!(Intrinsic(format!("{} called on 0", intrinsic_name)));
+                        throw_unsup!(Intrinsic(format!("{} called on 0", intrinsic_name)))
                     }
                     numeric_intrinsic(intrinsic_name.trim_end_matches("_nonzero"), bits, kind)?
                 } else {
@@ -190,9 +188,9 @@ pub fn emulate_intrinsic(
                 if overflowed {
                     let layout = self.layout_of(substs.type_at(0))?;
                     let r_val =  r.to_scalar()?.to_bits(layout.size)?;
-                    return err!(Intrinsic(
-                        format!("Overflowing shift by {} in {}", r_val, intrinsic_name),
-                    ));
+                    throw_unsup!(
+                        Intrinsic(format!("Overflowing shift by {} in {}", r_val, intrinsic_name))
+                    )
                 }
                 self.write_scalar(val, dest)?;
             }
@@ -250,7 +248,7 @@ pub fn hook_fn(
             let file = Symbol::intern(self.read_str(file_place)?);
             let line = self.read_scalar(line.into())?.to_u32()?;
             let col = self.read_scalar(col.into())?.to_u32()?;
-            return Err(InterpError::Panic(PanicMessage::Panic { msg, file, line, col }).into());
+            throw_panic!(Panic { msg, file, line, col })
         } else if Some(def_id) == self.tcx.lang_items().begin_panic_fn() {
             assert!(args.len() == 2);
             // &'static str, &(&'static str, u32, u32)
@@ -268,7 +266,7 @@ pub fn hook_fn(
             let file = Symbol::intern(self.read_str(file_place)?);
             let line = self.read_scalar(line.into())?.to_u32()?;
             let col = self.read_scalar(col.into())?.to_u32()?;
-            return Err(InterpError::Panic(PanicMessage::Panic { msg, file, line, col }).into());
+            throw_panic!(Panic { msg, file, line, col })
         } else {
             return Ok(false);
         }
index e3f16a3c9ea452432b33ed47ebd2b70b0c8e6dcf..78902b101663416b4af8de19ec5629c4ab83af18 100644 (file)
@@ -10,7 +10,7 @@
 use rustc::ty::{self, TyCtxt};
 
 use super::{
-    Allocation, AllocId, InterpResult, InterpError, Scalar, AllocationExtra,
+    Allocation, AllocId, InterpResult, Scalar, AllocationExtra,
     InterpCx, PlaceTy, OpTy, ImmTy, MemoryKind, Pointer, Memory,
 };
 
@@ -240,9 +240,9 @@ fn int_to_ptr(
         int: u64,
     ) -> InterpResult<'tcx, Pointer<Self::PointerTag>> {
         Err((if int == 0 {
-            InterpError::InvalidNullPointerUsage
+            err_unsup!(InvalidNullPointerUsage)
         } else {
-            InterpError::ReadBytesAsPointer
+            err_unsup!(ReadBytesAsPointer)
         }).into())
     }
 
@@ -251,6 +251,6 @@ fn ptr_to_int(
         _mem: &Memory<'mir, 'tcx, Self>,
         _ptr: Pointer<Self::PointerTag>,
     ) -> InterpResult<'tcx, u64> {
-        err!(ReadPointerAsBytes)
+        throw_unsup!(ReadPointerAsBytes)
     }
 }
index 87dd7738410ee8f4d054c51d3bc9c60be9de6ba0..a1574cd5935e9f475f9c866fe46c3360f22d2c27 100644 (file)
@@ -18,7 +18,7 @@
 
 use super::{
     Pointer, AllocId, Allocation, GlobalId, AllocationExtra,
-    InterpResult, Scalar, InterpError, GlobalAlloc, PointerArithmetic,
+    InterpResult, Scalar, GlobalAlloc, PointerArithmetic,
     Machine, AllocMap, MayLeak, ErrorHandled, CheckInAllocMsg,
 };
 
@@ -66,10 +66,9 @@ pub fn as_instance(self) -> InterpResult<'tcx, Instance<'tcx>> {
         match self {
             FnVal::Instance(instance) =>
                 Ok(instance),
-            FnVal::Other(_) =>
-                err!(MachineError(
-                    format!("Expected instance function pointer, got 'other' pointer")
-                )),
+            FnVal::Other(_) => throw_unsup!(MachineError(format!(
+                "Expected instance function pointer, got 'other' pointer"
+            ))),
         }
     }
 }
@@ -203,7 +202,7 @@ pub fn reallocate(
         kind: MemoryKind<M::MemoryKinds>,
     ) -> InterpResult<'tcx, Pointer<M::PointerTag>> {
         if ptr.offset.bytes() != 0 {
-            return err!(ReallocateNonBasePtr);
+            throw_unsup!(ReallocateNonBasePtr)
         }
 
         // For simplicities' sake, we implement reallocate as "alloc, copy, dealloc".
@@ -244,41 +243,37 @@ pub fn deallocate(
         trace!("deallocating: {}", ptr.alloc_id);
 
         if ptr.offset.bytes() != 0 {
-            return err!(DeallocateNonBasePtr);
+            throw_unsup!(DeallocateNonBasePtr)
         }
 
         let (alloc_kind, mut alloc) = match self.alloc_map.remove(&ptr.alloc_id) {
             Some(alloc) => alloc,
             None => {
                 // Deallocating static memory -- always an error
-                return match self.tcx.alloc_map.lock().get(ptr.alloc_id) {
-                    Some(GlobalAlloc::Function(..)) => err!(DeallocatedWrongMemoryKind(
+                return Err(match self.tcx.alloc_map.lock().get(ptr.alloc_id) {
+                    Some(GlobalAlloc::Function(..)) => err_unsup!(DeallocatedWrongMemoryKind(
                         "function".to_string(),
                         format!("{:?}", kind),
                     )),
-                    Some(GlobalAlloc::Static(..)) |
-                    Some(GlobalAlloc::Memory(..)) => err!(DeallocatedWrongMemoryKind(
-                        "static".to_string(),
-                        format!("{:?}", kind),
-                    )),
-                    None => err!(DoubleFree)
+                    Some(GlobalAlloc::Static(..)) | Some(GlobalAlloc::Memory(..)) => err_unsup!(
+                        DeallocatedWrongMemoryKind("static".to_string(), format!("{:?}", kind))
+                    ),
+                    None => err_unsup!(DoubleFree),
                 }
+                .into());
             }
         };
 
         if alloc_kind != kind {
-            return err!(DeallocatedWrongMemoryKind(
+            throw_unsup!(DeallocatedWrongMemoryKind(
                 format!("{:?}", alloc_kind),
                 format!("{:?}", kind),
-            ));
+            ))
         }
         if let Some((size, align)) = old_size_and_align {
             if size.bytes() != alloc.bytes.len() as u64 || align != alloc.align {
                 let bytes = Size::from_bytes(alloc.bytes.len() as u64);
-                return err!(IncorrectAllocationInformation(size,
-                                                           bytes,
-                                                           align,
-                                                           alloc.align));
+                throw_unsup!(IncorrectAllocationInformation(size, bytes, align, alloc.align))
             }
         }
 
@@ -323,7 +318,7 @@ fn check_offset_align(offset: u64, align: Align) -> InterpResult<'static> {
             } else {
                 // The biggest power of two through which `offset` is divisible.
                 let offset_pow2 = 1 << offset.trailing_zeros();
-                err!(AlignmentCheckFailed {
+                throw_unsup!(AlignmentCheckFailed {
                     has: Align::from_bytes(offset_pow2).unwrap(),
                     required: align,
                 })
@@ -345,7 +340,7 @@ fn check_offset_align(offset: u64, align: Align) -> InterpResult<'static> {
                 assert!(size.bytes() == 0);
                 // Must be non-NULL and aligned.
                 if bits == 0 {
-                    return err!(InvalidNullPointerUsage);
+                    throw_unsup!(InvalidNullPointerUsage)
                 }
                 check_offset_align(bits, align)?;
                 None
@@ -366,10 +361,10 @@ fn check_offset_align(offset: u64, align: Align) -> InterpResult<'static> {
                     // got picked we might be aligned even if this check fails.
                     // We instead have to fall back to converting to an integer and checking
                     // the "real" alignment.
-                    return err!(AlignmentCheckFailed {
+                    throw_unsup!(AlignmentCheckFailed {
                         has: alloc_align,
                         required: align,
-                    });
+                    })
                 }
                 check_offset_align(ptr.offset.bytes(), align)?;
 
@@ -417,9 +412,9 @@ fn get_static_alloc(
             Some(GlobalAlloc::Memory(mem)) =>
                 Cow::Borrowed(mem),
             Some(GlobalAlloc::Function(..)) =>
-                return err!(DerefFunctionPointer),
+                throw_unsup!(DerefFunctionPointer),
             None =>
-                return err!(DanglingPointerDeref),
+                throw_unsup!(DanglingPointerDeref),
             Some(GlobalAlloc::Static(def_id)) => {
                 // We got a "lazy" static that has not been computed yet.
                 if tcx.is_foreign_item(def_id) {
@@ -440,8 +435,10 @@ fn get_static_alloc(
                             // for statics
                             assert!(tcx.is_static(def_id));
                             match err {
-                                ErrorHandled::Reported => InterpError::ReferencedConstant,
-                                ErrorHandled::TooGeneric => InterpError::TooGeneric,
+                                ErrorHandled::Reported =>
+                                    err_inval!(ReferencedConstant),
+                                ErrorHandled::TooGeneric =>
+                                    err_inval!(TooGeneric),
                             }
                         })?;
                     // Make sure we use the ID of the resolved memory, not the lazy one!
@@ -505,11 +502,11 @@ pub fn get_mut(
             // to give us a cheap reference.
             let alloc = Self::get_static_alloc(memory_extra, tcx, id)?;
             if alloc.mutability == Mutability::Immutable {
-                return err!(ModifiedConstantMemory);
+                throw_unsup!(ModifiedConstantMemory)
             }
             match M::STATIC_KIND {
                 Some(kind) => Ok((MemoryKind::Machine(kind), alloc.into_owned())),
-                None => err!(ModifiedStatic),
+                None => throw_unsup!(ModifiedStatic),
             }
         });
         // Unpack the error type manually because type inference doesn't
@@ -519,7 +516,7 @@ pub fn get_mut(
             Ok(a) => {
                 let a = &mut a.1;
                 if a.mutability == Mutability::Immutable {
-                    return err!(ModifiedConstantMemory);
+                    throw_unsup!(ModifiedConstantMemory)
                 }
                 Ok(a)
             }
@@ -548,7 +545,7 @@ pub fn get_size_and_align(
         if let Ok(_) = self.get_fn_alloc(id) {
             return if let AllocCheck::Dereferencable = liveness {
                 // The caller requested no function pointers.
-                err!(DerefFunctionPointer)
+                throw_unsup!(DerefFunctionPointer)
             } else {
                 Ok((Size::ZERO, Align::from_bytes(1).unwrap()))
             };
@@ -579,7 +576,7 @@ pub fn get_size_and_align(
                     .expect("deallocated pointers should all be recorded in \
                             `dead_alloc_map`"))
             } else {
-                err!(DanglingPointerDeref)
+                throw_unsup!(DanglingPointerDeref)
             },
         }
     }
@@ -591,7 +588,7 @@ fn get_fn_alloc(&self, id: AllocId) -> InterpResult<'tcx, FnVal<'tcx, M::ExtraFn
         } else {
             match self.tcx.alloc_map.lock().get(id) {
                 Some(GlobalAlloc::Function(instance)) => Ok(FnVal::Instance(instance)),
-                _ => Err(InterpError::ExecuteMemory.into()),
+                _ => throw_unsup!(ExecuteMemory),
             }
         }
     }
@@ -602,7 +599,7 @@ pub fn get_fn(
     ) -> InterpResult<'tcx, FnVal<'tcx, M::ExtraFnVal>> {
         let ptr = self.force_ptr(ptr)?; // We definitely need a pointer value.
         if ptr.offset.bytes() != 0 {
-            return err!(InvalidFunctionPointer);
+            throw_unsup!(InvalidFunctionPointer)
         }
         self.get_fn_alloc(ptr.alloc_id)
     }
@@ -837,9 +834,9 @@ pub fn copy_repeatedly(
                     if (src.offset <= dest.offset && src.offset + size > dest.offset) ||
                         (dest.offset <= src.offset && dest.offset + size > src.offset)
                     {
-                        return err!(Intrinsic(
+                        throw_unsup!(Intrinsic(
                             "copy_nonoverlapping called on overlapping ranges".to_string(),
-                        ));
+                        ))
                     }
                 }
 
index 1816171d7b1276ecbd6f87ac23a2f9f4bbf5cc44..e64a474b4ca7171c2a907ffe59b6c5455ec964cd 100644 (file)
@@ -11,8 +11,7 @@
 use rustc::mir::interpret::{
     GlobalId, AllocId,
     ConstValue, Pointer, Scalar,
-    InterpResult, InterpError,
-    sign_extend, truncate,
+    InterpResult, sign_extend, truncate,
 };
 use super::{
     InterpCx, Machine,
@@ -331,8 +330,9 @@ pub fn read_str(
     ) -> InterpResult<'tcx, &str> {
         let len = mplace.len(self)?;
         let bytes = self.memory.read_bytes(mplace.ptr, Size::from_bytes(len as u64))?;
-        let str = ::std::str::from_utf8(bytes)
-            .map_err(|err| InterpError::ValidationFailure(err.to_string()))?;
+        let str = ::std::str::from_utf8(bytes).map_err(|err| {
+            err_unsup!(ValidationFailure(err.to_string()))
+        })?;
         Ok(str)
     }
 
@@ -459,7 +459,8 @@ pub(super) fn eval_place_to_op(
 
         mir_place.iterate(|place_base, place_projection| {
             let mut op = match place_base {
-                PlaceBase::Local(mir::RETURN_PLACE) => return err!(ReadFromReturnPointer),
+                PlaceBase::Local(mir::RETURN_PLACE) =>
+                    throw_unsup!(ReadFromReturnPointer),
                 PlaceBase::Local(local) => {
                     // Do not use the layout passed in as argument if the base we are looking at
                     // here is not the entire place.
@@ -530,7 +531,9 @@ pub(super) fn eval_operands(
         };
         // Early-return cases.
         match val.val {
-            ConstValue::Param(_) => return err!(TooGeneric), // FIXME(oli-obk): try to monomorphize
+            ConstValue::Param(_) =>
+                // FIXME(oli-obk): try to monomorphize
+                throw_inval!(TooGeneric),
             ConstValue::Unevaluated(def_id, substs) => {
                 let instance = self.resolve(def_id, substs)?;
                 return Ok(OpTy::from(self.const_eval_raw(GlobalId {
@@ -604,7 +607,8 @@ pub fn read_discriminant(
             layout::DiscriminantKind::Tag => {
                 let bits_discr = match raw_discr.to_bits(discr_val.layout.size) {
                     Ok(raw_discr) => raw_discr,
-                    Err(_) => return err!(InvalidDiscriminant(raw_discr.erase_tag())),
+                    Err(_) =>
+                        throw_unsup!(InvalidDiscriminant(raw_discr.erase_tag())),
                 };
                 let real_discr = if discr_val.layout.ty.is_signed() {
                     // going from layout tag type to typeck discriminant type
@@ -630,7 +634,9 @@ pub fn read_discriminant(
                         .discriminants(*def_id, self.tcx.tcx)
                         .find(|(_, var)| var.val == real_discr),
                     _ => bug!("tagged layout for non-adt non-generator"),
-                }.ok_or_else(|| InterpError::InvalidDiscriminant(raw_discr.erase_tag()))?;
+                }.ok_or_else(
+                    || err_unsup!(InvalidDiscriminant(raw_discr.erase_tag()))
+                )?;
                 (real_discr, index.0)
             },
             layout::DiscriminantKind::Niche {
@@ -640,15 +646,16 @@ pub fn read_discriminant(
             } => {
                 let variants_start = niche_variants.start().as_u32() as u128;
                 let variants_end = niche_variants.end().as_u32() as u128;
-                let raw_discr = raw_discr.not_undef()
-                    .map_err(|_| InterpError::InvalidDiscriminant(ScalarMaybeUndef::Undef))?;
+                let raw_discr = raw_discr.not_undef().map_err(|_| {
+                    err_unsup!(InvalidDiscriminant(ScalarMaybeUndef::Undef))
+                })?;
                 match raw_discr.to_bits_or_ptr(discr_val.layout.size, self) {
                     Err(ptr) => {
                         // The niche must be just 0 (which an inbounds pointer value never is)
                         let ptr_valid = niche_start == 0 && variants_start == variants_end &&
                             !self.memory.ptr_may_be_null(ptr);
                         if !ptr_valid {
-                            return err!(InvalidDiscriminant(raw_discr.erase_tag().into()));
+                            throw_unsup!(InvalidDiscriminant(raw_discr.erase_tag().into()))
                         }
                         (dataful_variant.as_u32() as u128, dataful_variant)
                     },
index b4edee72a4d19bb901406d5fc9c94e70ac5bd7e4..a942da5771b00b3606d25a518c4c67aaa4289882 100644 (file)
@@ -2,7 +2,7 @@
 use rustc::ty::{self, layout::TyLayout};
 use syntax::ast::FloatTy;
 use rustc_apfloat::Float;
-use rustc::mir::interpret::{InterpResult, PanicMessage, Scalar};
+use rustc::mir::interpret::{InterpResult, Scalar};
 
 use super::{InterpCx, PlaceTy, Immediate, Machine, ImmTy};
 
@@ -155,7 +155,7 @@ fn binary_int_op(
                 r,
                 right_layout.ty
             );
-            return err!(Unimplemented(msg));
+            throw_unsup!(Unimplemented(msg))
         }
 
         // Operations that need special treatment for signed integers
@@ -173,8 +173,8 @@ fn binary_int_op(
                 return Ok((Scalar::from_bool(op(&l, &r)), false));
             }
             let op: Option<fn(i128, i128) -> (i128, bool)> = match bin_op {
-                Div if r == 0 => return err!(Panic(PanicMessage::DivisionByZero)),
-                Rem if r == 0 => return err!(Panic(PanicMessage::RemainderByZero)),
+                Div if r == 0 => throw_panic!(DivisionByZero),
+                Rem if r == 0 => throw_panic!(RemainderByZero),
                 Div => Some(i128::overflowing_div),
                 Rem => Some(i128::overflowing_rem),
                 Add => Some(i128::overflowing_add),
@@ -231,8 +231,8 @@ fn binary_int_op(
                     Add => u128::overflowing_add,
                     Sub => u128::overflowing_sub,
                     Mul => u128::overflowing_mul,
-                    Div if r == 0 => return err!(Panic(PanicMessage::DivisionByZero)),
-                    Rem if r == 0 => return err!(Panic(PanicMessage::RemainderByZero)),
+                    Div if r == 0 => throw_panic!(DivisionByZero),
+                    Rem if r == 0 => throw_panic!(RemainderByZero),
                     Div => u128::overflowing_div,
                     Rem => u128::overflowing_rem,
                     _ => bug!(),
@@ -250,7 +250,7 @@ fn binary_int_op(
                     r,
                     right_layout.ty,
                 );
-                return err!(Unimplemented(msg));
+                throw_unsup!(Unimplemented(msg))
             }
         };
 
index 8fe882934dfb58c9934b5a400a39173eb044ef7e..f66c4adf763976a33ad969e3681b219efa6b1f01 100644 (file)
@@ -13,8 +13,8 @@
 
 use super::{
     GlobalId, AllocId, Allocation, Scalar, InterpResult, Pointer, PointerArithmetic,
-    InterpCx, Machine, AllocMap, AllocationExtra, PanicMessage,
-    RawConst, Immediate, ImmTy, ScalarMaybeUndef, Operand, OpTy, MemoryKind, LocalValue
+    InterpCx, Machine, AllocMap, AllocationExtra,
+    RawConst, Immediate, ImmTy, ScalarMaybeUndef, Operand, OpTy, MemoryKind, LocalValue,
 };
 
 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
@@ -356,7 +356,7 @@ pub fn mplace_field(
                     // This can be violated because this runs during promotion on code where the
                     // type system has not yet ensured that such things don't happen.
                     debug!("tried to access element {} of array/slice with length {}", field, len);
-                    return err!(Panic(PanicMessage::BoundsCheck { len, index: field }));
+                    throw_panic!(BoundsCheck { len, index: field });
                 }
                 stride * field
             }
@@ -622,7 +622,7 @@ pub fn eval_place(
                                 .layout_of(self.monomorphize(self.frame().body.return_ty())?)?,
                         }
                     }
-                    None => return err!(InvalidNullPointerUsage),
+                    None => throw_unsup!(InvalidNullPointerUsage),
                 },
                 PlaceBase::Local(local) => PlaceTy {
                     // This works even for dead/uninitialized locals; we check further when writing
index ad631793a082751b6ffc13f23e2240a58b3e9a0d..70a297c866280af83e6b16354bbcaffd3235740f 100644 (file)
@@ -11,8 +11,7 @@
 use rustc::mir;
 use rustc::mir::interpret::{
     AllocId, Pointer, Scalar,
-    Relocations, Allocation, UndefMask,
-    InterpResult, InterpError,
+    Relocations, Allocation, UndefMask, InterpResult,
 };
 
 use rustc::ty::{self, TyCtxt};
@@ -77,7 +76,7 @@ pub fn observe_and_analyze(
         }
 
         // Second cycle
-        Err(InterpError::InfiniteLoop.into())
+        throw_exhaust!(InfiniteLoop)
     }
 }
 
index 246c90ba48e3aa3661ca61a81dbaf4ea932a0a0a..95824d0ebc16608641930c2fc5af39f4292a4301 100644 (file)
@@ -121,7 +121,7 @@ fn statement(&mut self, stmt: &mir::Statement<'tcx>) -> InterpResult<'tcx> {
             // size of MIR constantly.
             Nop => {}
 
-            InlineAsm { .. } => return err!(InlineAsm),
+            InlineAsm { .. } => throw_unsup!(InlineAsm),
         }
 
         self.stack[frame_idx].stmt += 1;
index 27bd0f88896340d1a8df827de43555e1334f5c3c..d4bc8f460e894d98fa17cc90c34768640358540c 100644 (file)
@@ -7,7 +7,7 @@
 use rustc_target::spec::abi::Abi;
 
 use super::{
-    InterpResult, PointerArithmetic, InterpError, Scalar,
+    InterpResult, PointerArithmetic, Scalar,
     InterpCx, Machine, Immediate, OpTy, ImmTy, PlaceTy, MPlaceTy, StackPopCleanup, FnVal,
 };
 
@@ -19,7 +19,7 @@ pub fn goto_block(&mut self, target: Option<mir::BasicBlock>) -> InterpResult<'t
             self.frame_mut().stmt = 0;
             Ok(())
         } else {
-            err!(Unreachable)
+            throw_ub!(Unreachable)
         }
     }
 
@@ -89,7 +89,7 @@ pub(super) fn eval_terminator(
                     },
                     _ => {
                         let msg = format!("can't handle callee of type {:?}", func.layout.ty);
-                        return err!(Unimplemented(msg));
+                        throw_unsup!(Unimplemented(msg))
                     }
                 };
                 let args = self.eval_operands(args)?;
@@ -135,32 +135,30 @@ pub(super) fn eval_terminator(
                     self.goto_block(Some(target))?;
                 } else {
                     // Compute error message
-                    use rustc::mir::interpret::PanicMessage::*;
-                    return match msg {
+                    use rustc::mir::interpret::PanicInfo::*;
+                    return Err(match msg {
                         BoundsCheck { ref len, ref index } => {
-                            let len = self.read_immediate(self.eval_operand(len, None)?)
-                                .expect("can't eval len").to_scalar()?
+                            let len = self
+                                .read_immediate(self.eval_operand(len, None)?)
+                                .expect("can't eval len")
+                                .to_scalar()?
                                 .to_bits(self.memory().pointer_size())? as u64;
-                            let index = self.read_immediate(self.eval_operand(index, None)?)
-                                .expect("can't eval index").to_scalar()?
+                            let index = self
+                                .read_immediate(self.eval_operand(index, None)?)
+                                .expect("can't eval index")
+                                .to_scalar()?
                                 .to_bits(self.memory().pointer_size())? as u64;
-                            err!(Panic(BoundsCheck { len, index }))
+                            err_panic!(BoundsCheck { len, index })
                         }
-                        Overflow(op) =>
-                            err!(Panic(Overflow(*op))),
-                        OverflowNeg =>
-                            err!(Panic(OverflowNeg)),
-                        DivisionByZero =>
-                            err!(Panic(DivisionByZero)),
-                        RemainderByZero =>
-                            err!(Panic(RemainderByZero)),
-                        GeneratorResumedAfterReturn =>
-                            err!(Panic(GeneratorResumedAfterReturn)),
-                        GeneratorResumedAfterPanic =>
-                            err!(Panic(GeneratorResumedAfterPanic)),
-                        Panic { .. } =>
-                            bug!("`Panic` variant cannot occur in MIR"),
-                    };
+                        Overflow(op) => err_panic!(Overflow(*op)),
+                        OverflowNeg => err_panic!(OverflowNeg),
+                        DivisionByZero => err_panic!(DivisionByZero),
+                        RemainderByZero => err_panic!(RemainderByZero),
+                        GeneratorResumedAfterReturn => err_panic!(GeneratorResumedAfterReturn),
+                        GeneratorResumedAfterPanic => err_panic!(GeneratorResumedAfterPanic),
+                        Panic { .. } => bug!("`Panic` variant cannot occur in MIR"),
+                    }
+                    .into());
                 }
             }
 
@@ -173,7 +171,7 @@ pub(super) fn eval_terminator(
                                       `simplify_branches` mir pass"),
             FalseUnwind { .. } => bug!("should have been eliminated by\
                                        `simplify_branches` mir pass"),
-            Unreachable => return err!(Unreachable),
+            Unreachable => throw_ub!(Unreachable),
         }
 
         Ok(())
@@ -220,13 +218,13 @@ fn pass_argument(
             return Ok(());
         }
         let caller_arg = caller_arg.next()
-            .ok_or_else(|| InterpError::FunctionArgCountMismatch)?;
+            .ok_or_else(|| err_unsup!(FunctionArgCountMismatch)) ?;
         if rust_abi {
             debug_assert!(!caller_arg.layout.is_zst(), "ZSTs must have been already filtered out");
         }
         // Now, check
         if !Self::check_argument_compat(rust_abi, caller_arg.layout, callee_arg.layout) {
-            return err!(FunctionArgMismatch(caller_arg.layout.ty, callee_arg.layout.ty));
+            throw_unsup!(FunctionArgMismatch(caller_arg.layout.ty, callee_arg.layout.ty))
         }
         // We allow some transmutes here
         self.copy_op_transmute(caller_arg, callee_arg)
@@ -254,13 +252,13 @@ fn eval_fn_call(
         match instance.def {
             ty::InstanceDef::Intrinsic(..) => {
                 if caller_abi != Abi::RustIntrinsic {
-                    return err!(FunctionAbiMismatch(caller_abi, Abi::RustIntrinsic));
+                    throw_unsup!(FunctionAbiMismatch(caller_abi, Abi::RustIntrinsic))
                 }
                 // The intrinsic itself cannot diverge, so if we got here without a return
                 // place... (can happen e.g., for transmute returning `!`)
                 let dest = match dest {
                     Some(dest) => dest,
-                    None => return err!(Unreachable)
+                    None => throw_ub!(Unreachable)
                 };
                 M::call_intrinsic(self, instance, args, dest)?;
                 // No stack frame gets pushed, the main loop will just act as if the
@@ -295,7 +293,7 @@ fn eval_fn_call(
                             abi,
                     };
                     if normalize_abi(caller_abi) != normalize_abi(callee_abi) {
-                        return err!(FunctionAbiMismatch(caller_abi, callee_abi));
+                        throw_unsup!(FunctionAbiMismatch(caller_abi, callee_abi))
                     }
                 }
 
@@ -390,7 +388,7 @@ fn eval_fn_call(
                     // Now we should have no more caller args
                     if caller_iter.next().is_some() {
                         trace!("Caller has passed too many args");
-                        return err!(FunctionArgCountMismatch);
+                        throw_unsup!(FunctionArgCountMismatch)
                     }
                     // Don't forget to check the return type!
                     if let Some(caller_ret) = dest {
@@ -402,15 +400,15 @@ fn eval_fn_call(
                             caller_ret.layout,
                             callee_ret.layout,
                         ) {
-                            return err!(FunctionRetMismatch(
-                                caller_ret.layout.ty, callee_ret.layout.ty
-                            ));
+                            throw_unsup!(
+                                FunctionRetMismatch(caller_ret.layout.ty, callee_ret.layout.ty)
+                            )
                         }
                     } else {
                         let local = mir::RETURN_PLACE;
                         let ty = self.frame().body.local_decls[local].ty;
                         if !self.tcx.is_ty_uninhabited_from_any_module(ty) {
-                            return err!(FunctionRetMismatch(self.tcx.types.never, ty));
+                            throw_unsup!(FunctionRetMismatch(self.tcx.types.never, ty))
                         }
                     }
                     Ok(())
index e7363f6876c28ce7abeb9a2370d4eeb60fb685e0..e55b0d0fb1f2a56e6f572a3b78b6fd2a5070415c 100644 (file)
@@ -1,8 +1,8 @@
 use rustc::ty::{self, Ty, Instance};
 use rustc::ty::layout::{Size, Align, LayoutOf};
-use rustc::mir::interpret::{Scalar, Pointer, InterpResult, PointerArithmetic};
+use rustc::mir::interpret::{Scalar, Pointer, InterpResult, PointerArithmetic,};
 
-use super::{InterpCx, InterpError, Machine, MemoryKind, FnVal};
+use super::{InterpCx, Machine, MemoryKind, FnVal};
 
 impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     /// Creates a dynamic vtable for the given type and vtable origin. This is used only for
@@ -83,7 +83,7 @@ pub fn get_vtable(
                     self.param_env,
                     def_id,
                     substs,
-                ).ok_or_else(|| InterpError::TooGeneric)?;
+                ).ok_or_else(|| err_inval!(TooGeneric))?;
                 let fn_ptr = self.memory.create_fn_alloc(FnVal::Instance(instance));
                 let method_ptr = vtable.offset(ptr_size * (3 + i as u64), self)?;
                 self.memory
index da9780ac0a305ba93278f55fca283a889a9599be..072c9afc50ae024745fa1c2535d0e009379b0e82 100644 (file)
 use std::hash::Hash;
 
 use super::{
-    GlobalAlloc, InterpResult, InterpError,
+    GlobalAlloc, InterpResult,
     OpTy, Machine, InterpCx, ValueVisitor, MPlaceTy,
 };
 
-macro_rules! validation_failure {
+macro_rules! throw_validation_failure {
     ($what:expr, $where:expr, $details:expr) => {{
         let where_ = path_format(&$where);
         let where_ = if where_.is_empty() {
@@ -22,7 +22,7 @@ macro_rules! validation_failure {
         } else {
             format!(" at {}", where_)
         };
-        err!(ValidationFailure(format!(
+        throw_unsup!(ValidationFailure(format!(
             "encountered {}{}, but expected {}",
             $what, where_, $details,
         )))
@@ -34,7 +34,7 @@ macro_rules! validation_failure {
         } else {
             format!(" at {}", where_)
         };
-        err!(ValidationFailure(format!(
+        throw_unsup!(ValidationFailure(format!(
             "encountered {}{}",
             $what, where_,
         )))
@@ -45,14 +45,14 @@ macro_rules! try_validation {
     ($e:expr, $what:expr, $where:expr, $details:expr) => {{
         match $e {
             Ok(x) => x,
-            Err(_) => return validation_failure!($what, $where, $details),
+            Err(_) => throw_validation_failure!($what, $where, $details),
         }
     }};
 
     ($e:expr, $what:expr, $where:expr) => {{
         match $e {
             Ok(x) => x,
-            Err(_) => return validation_failure!($what, $where),
+            Err(_) => throw_validation_failure!($what, $where),
         }
     }}
 }
@@ -297,12 +297,12 @@ fn visit_value(&mut self, op: OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx>
         match self.walk_value(op) {
             Ok(()) => Ok(()),
             Err(err) => match err.kind {
-                InterpError::InvalidDiscriminant(val) =>
-                    validation_failure!(
+                err_unsup!(InvalidDiscriminant(val)) =>
+                    throw_validation_failure!(
                         val, self.path, "a valid enum discriminant"
                     ),
-                InterpError::ReadPointerAsBytes =>
-                    validation_failure!(
+                err_unsup!(ReadPointerAsBytes) =>
+                    throw_validation_failure!(
                         "a pointer", self.path, "plain (non-pointer) bytes"
                     ),
                 _ => Err(err),
@@ -406,19 +406,19 @@ fn visit_primitive(&mut self, value: OpTy<'tcx, M::PointerTag>) -> InterpResult<
                             ptr, size, align
                         );
                         match err.kind {
-                            InterpError::InvalidNullPointerUsage =>
-                                return validation_failure!("NULL reference", self.path),
-                            InterpError::AlignmentCheckFailed { required, has } =>
-                                return validation_failure!(format!("unaligned reference \
+                            err_unsup!(InvalidNullPointerUsage) =>
+                                throw_validation_failure!("NULL reference", self.path),
+                            err_unsup!(AlignmentCheckFailed { required, has }) =>
+                                throw_validation_failure!(format!("unaligned reference \
                                     (required {} byte alignment but found {})",
                                     required.bytes(), has.bytes()), self.path),
-                            InterpError::ReadBytesAsPointer =>
-                                return validation_failure!(
+                            err_unsup!(ReadBytesAsPointer) =>
+                                throw_validation_failure!(
                                     "dangling reference (created from integer)",
                                     self.path
                                 ),
                             _ =>
-                                return validation_failure!(
+                                throw_validation_failure!(
                                     "dangling reference (not entirely in bounds)",
                                     self.path
                                 ),
@@ -478,7 +478,7 @@ fn visit_primitive(&mut self, value: OpTy<'tcx, M::PointerTag>) -> InterpResult<
 
     fn visit_uninhabited(&mut self) -> InterpResult<'tcx>
     {
-        validation_failure!("a value of an uninhabited type", self.path)
+        throw_validation_failure!("a value of an uninhabited type", self.path)
     }
 
     fn visit_scalar(
@@ -511,27 +511,27 @@ fn visit_scalar(
                 if lo == 1 && hi == max_hi {
                     // Only NULL is the niche.  So make sure the ptr is NOT NULL.
                     if self.ecx.memory.ptr_may_be_null(ptr) {
-                        return validation_failure!(
+                        throw_validation_failure!(
                             "a potentially NULL pointer",
                             self.path,
                             format!(
                                 "something that cannot possibly fail to be {}",
                                 wrapping_range_format(&layout.valid_range, max_hi)
                             )
-                        );
+                        )
                     }
                     return Ok(());
                 } else {
                     // Conservatively, we reject, because the pointer *could* have a bad
                     // value.
-                    return validation_failure!(
+                    throw_validation_failure!(
                         "a pointer",
                         self.path,
                         format!(
                             "something that cannot possibly fail to be {}",
                             wrapping_range_format(&layout.valid_range, max_hi)
                         )
-                    );
+                    )
                 }
             }
             Ok(data) =>
@@ -541,7 +541,7 @@ fn visit_scalar(
         if wrapping_range_contains(&layout.valid_range, bits) {
             Ok(())
         } else {
-            validation_failure!(
+            throw_validation_failure!(
                 bits,
                 self.path,
                 format!("something {}", wrapping_range_format(&layout.valid_range, max_hi))
@@ -608,16 +608,14 @@ fn visit_aggregate(
                     Err(err) => {
                         // For some errors we might be able to provide extra information
                         match err.kind {
-                            InterpError::ReadUndefBytes(offset) => {
+                            err_unsup!(ReadUndefBytes(offset)) => {
                                 // Some byte was undefined, determine which
                                 // element that byte belongs to so we can
                                 // provide an index.
                                 let i = (offset.bytes() / ty_size.bytes()) as usize;
                                 self.path.push(PathElem::ArrayElem(i));
 
-                                return validation_failure!(
-                                    "undefined bytes", self.path
-                                )
+                                throw_validation_failure!("undefined bytes", self.path)
                             },
                             // Other errors shouldn't be possible
                             _ => return Err(err),
index 7a2d78b2e986b670626c7c878ef93ddefc402104..a450ec32e1a478410a432d9c971c7d9b32f6dbab 100644 (file)
@@ -13,7 +13,7 @@
 use rustc::mir::visit::{
     Visitor, PlaceContext, MutatingUseContext, MutVisitor, NonMutatingUseContext,
 };
-use rustc::mir::interpret::{Scalar, GlobalId, InterpResult, InterpError, PanicMessage};
+use rustc::mir::interpret::{Scalar, GlobalId, InterpResult, PanicInfo};
 use rustc::ty::{self, Instance, ParamEnv, Ty, TyCtxt};
 use syntax_pos::{Span, DUMMY_SP};
 use rustc::ty::subst::InternalSubsts;
@@ -258,87 +258,14 @@ fn use_ecx<F, T>(
                 let diagnostic = error_to_const_error(&self.ecx, error);
                 use rustc::mir::interpret::InterpError::*;
                 match diagnostic.error {
-                    // don't report these, they make no sense in a const prop context
-                    | MachineError(_)
-                    | Exit(_)
-                    // at runtime these transformations might make sense
-                    // FIXME: figure out the rules and start linting
-                    | FunctionAbiMismatch(..)
-                    | FunctionArgMismatch(..)
-                    | FunctionRetMismatch(..)
-                    | FunctionArgCountMismatch
-                    // fine at runtime, might be a register address or sth
-                    | ReadBytesAsPointer
-                    // fine at runtime
-                    | ReadForeignStatic
-                    | Unimplemented(_)
-                    // don't report const evaluator limits
-                    | StackFrameLimitReached
-                    | NoMirFor(..)
-                    | InlineAsm
-                    => {},
-
-                    | InvalidMemoryAccess
-                    | DanglingPointerDeref
-                    | DoubleFree
-                    | InvalidFunctionPointer
-                    | InvalidBool
-                    | InvalidDiscriminant(..)
-                    | PointerOutOfBounds { .. }
-                    | InvalidNullPointerUsage
-                    | ValidationFailure(..)
-                    | InvalidPointerMath
-                    | ReadUndefBytes(_)
-                    | DeadLocal
-                    | InvalidBoolOp(_)
-                    | DerefFunctionPointer
-                    | ExecuteMemory
-                    | Intrinsic(..)
-                    | InvalidChar(..)
-                    | AbiViolation(_)
-                    | AlignmentCheckFailed{..}
-                    | CalledClosureAsFunction
-                    | VtableForArgumentlessMethod
-                    | ModifiedConstantMemory
-                    | ModifiedStatic
-                    | AssumptionNotHeld
-                    // FIXME: should probably be removed and turned into a bug! call
-                    | TypeNotPrimitive(_)
-                    | ReallocatedWrongMemoryKind(_, _)
-                    | DeallocatedWrongMemoryKind(_, _)
-                    | ReallocateNonBasePtr
-                    | DeallocateNonBasePtr
-                    | IncorrectAllocationInformation(..)
-                    | UnterminatedCString(_)
-                    | HeapAllocZeroBytes
-                    | HeapAllocNonPowerOfTwoAlignment(_)
-                    | Unreachable
-                    | ReadFromReturnPointer
-                    | ReferencedConstant
-                    | InfiniteLoop
-                    => {
-                        // FIXME: report UB here
-                    },
-
-                    | OutOfTls
-                    | TlsOutOfBounds
-                    | PathNotFound(_)
-                    => bug!("these should not be in rustc, but in miri's machine errors"),
-
-                    | Layout(_)
-                    | UnimplementedTraitSelection
-                    | TypeckError
-                    | TooGeneric
-                    // these are just noise
-                    => {},
-
-                    // non deterministic
-                    | ReadPointerAsBytes
-                    // FIXME: implement
-                    => {},
-
-                    | Panic(_)
-                    => {
+                    Exit(_) => bug!("the CTFE program cannot exit"),
+                    Unsupported(_)
+                    | UndefinedBehaviour(_)
+                    | InvalidProgram(_)
+                    | ResourceExhaustion(_) => {
+                        // Ignore these errors.
+                    }
+                    Panic(_) => {
                         diagnostic.report_as_lint(
                             self.ecx.tcx,
                             "this expression will panic at runtime",
@@ -515,7 +442,7 @@ fn const_prop(
                             // Need to do overflow check here: For actual CTFE, MIR
                             // generation emits code that does this before calling the op.
                             if prim.to_bits()? == (1 << (prim.layout.size.bits() - 1)) {
-                                return err!(Panic(PanicMessage::OverflowNeg));
+                                throw_panic!(OverflowNeg)
                             }
                         }
                         UnOp::Not => {
@@ -593,7 +520,7 @@ fn const_prop(
                     )
                 } else {
                     if overflow {
-                        let err = InterpError::Panic(PanicMessage::Overflow(op)).into();
+                        let err = err_panic!(Overflow(op)).into();
                         let _: Option<()> = self.use_ecx(source_info, |_| Err(err));
                         return None;
                     }
@@ -830,12 +757,12 @@ fn visit_terminator(
                             .as_local_hir_id(self.source.def_id())
                             .expect("some part of a failing const eval must be local");
                         let msg = match msg {
-                            PanicMessage::Overflow(_) |
-                            PanicMessage::OverflowNeg |
-                            PanicMessage::DivisionByZero |
-                            PanicMessage::RemainderByZero =>
+                            PanicInfo::Overflow(_) |
+                            PanicInfo::OverflowNeg |
+                            PanicInfo::DivisionByZero |
+                            PanicInfo::RemainderByZero =>
                                 msg.description().to_owned(),
-                            PanicMessage::BoundsCheck { ref len, ref index } => {
+                            PanicInfo::BoundsCheck { ref len, ref index } => {
                                 let len = self
                                     .eval_operand(len, source_info)
                                     .expect("len must be const");
index 5461a2e470c7e62a7e2ebb5d4ee23fb5e83586c5..94bb70e10aa53bda6d01b87dd69ef95704592f46 100644 (file)
@@ -1016,7 +1016,7 @@ fn create_generator_resume_function<'tcx>(
 
     let mut cases = create_cases(body, &transform, |point| Some(point.resume));
 
-    use rustc::mir::interpret::PanicMessage::{
+    use rustc::mir::interpret::PanicInfo::{
         GeneratorResumedAfterPanic,
         GeneratorResumedAfterReturn,
     };
index 585731fb30e578689faad9243c7cfeae97a3eff1..6e111f2423659ccbbcc359cb3da7869ad3f44b3c 100644 (file)
@@ -1055,7 +1055,7 @@ pub fn from_bytes_with_nul(bytes: &[u8])
     ///
     /// ```no_run
     /// # #![allow(unused_must_use)]
-    /// use std::ffi::{CString};
+    /// use std::ffi::CString;
     ///
     /// let ptr = CString::new("Hello").expect("CString::new failed").as_ptr();
     /// unsafe {
@@ -1071,7 +1071,7 @@ pub fn from_bytes_with_nul(bytes: &[u8])
     ///
     /// ```no_run
     /// # #![allow(unused_must_use)]
-    /// use std::ffi::{CString};
+    /// use std::ffi::CString;
     ///
     /// let hello = CString::new("Hello").expect("CString::new failed");
     /// let ptr = hello.as_ptr();
index 2a2df76d30c1d41111ba1c453d6b61bf736bada7..81c5ef135b245c76e87b8a8c00afd2a4c4661e63 100644 (file)
@@ -282,7 +282,10 @@ pub fn compile(
         quoted::TokenTree::Sequence(
             DelimSpan::dummy(),
             Lrc::new(quoted::SequenceRepetition {
-                tts: vec![quoted::TokenTree::token(token::Semi, def.span)],
+                tts: vec![quoted::TokenTree::token(
+                    if body.legacy { token::Semi } else { token::Comma },
+                    def.span,
+                )],
                 separator: None,
                 kleene: quoted::KleeneToken::new(quoted::KleeneOp::ZeroOrMore, def.span),
                 num_captures: 0,
index 1aac8bbb7aa46589d9d07a3af0017a1757f838ef..002aa2f891e4b599d6e23a76ac28c888e5e61a14 100644 (file)
@@ -368,7 +368,7 @@ pub fn stream_to_parser_with_base_dir<'a>(
 
 /// A sequence separator.
 pub struct SeqSep {
-    /// The seperator token.
+    /// The separator token.
     pub sep: Option<TokenKind>,
     /// `true` if a trailing separator is allowed.
     pub trailing_sep_allowed: bool,
index 7096d6799e2cdf3e7fe438cc28a544a39a9d73ab..8ca962a4419bdfc6385a20bd1e8023dd37301e20 100644 (file)
@@ -3592,7 +3592,15 @@ fn parse_pat_fields(&mut self) -> PResult<'a, (Vec<source_map::Spanned<ast::Fiel
         let mut etc_span = None;
 
         while self.token != token::CloseDelim(token::Brace) {
-            let attrs = self.parse_outer_attributes()?;
+            let attrs = match self.parse_outer_attributes() {
+                Ok(attrs) => attrs,
+                Err(err) => {
+                    if let Some(mut delayed) = delayed_err {
+                        delayed.emit();
+                    }
+                    return Err(err);
+                },
+            };
             let lo = self.token.span;
 
             // check that a comma comes after every field
diff --git a/src/test/ui/macros/issue-63102.rs b/src/test/ui/macros/issue-63102.rs
new file mode 100644 (file)
index 0000000..6af5b18
--- /dev/null
@@ -0,0 +1,8 @@
+// check-pass
+
+#![feature(decl_macro)]
+macro foo {
+    () => {},
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-63135.rs b/src/test/ui/parser/issue-63135.rs
new file mode 100644 (file)
index 0000000..d5f5f14
--- /dev/null
@@ -0,0 +1,3 @@
+// error-pattern: aborting due to 6 previous errors
+
+fn i(n{...,f #
diff --git a/src/test/ui/parser/issue-63135.stderr b/src/test/ui/parser/issue-63135.stderr
new file mode 100644 (file)
index 0000000..c0286d9
--- /dev/null
@@ -0,0 +1,44 @@
+error: this file contains an un-closed delimiter
+  --> $DIR/issue-63135.rs:3:16
+   |
+LL | fn i(n{...,f #
+   |     - -        ^
+   |     | |
+   |     | un-closed delimiter
+   |     un-closed delimiter
+
+error: expected field pattern, found `...`
+  --> $DIR/issue-63135.rs:3:8
+   |
+LL | fn i(n{...,f #
+   |        ^^^ help: to omit remaining fields, use one fewer `.`: `..`
+
+error: expected `}`, found `,`
+  --> $DIR/issue-63135.rs:3:11
+   |
+LL | fn i(n{...,f #
+   |        ---^
+   |        |  |
+   |        |  expected `}`
+   |        `..` must be at the end and cannot have a trailing comma
+
+error: expected `[`, found `}`
+  --> $DIR/issue-63135.rs:3:15
+   |
+LL | fn i(n{...,f #
+   |               ^ expected `[`
+
+error: expected `:`, found `)`
+  --> $DIR/issue-63135.rs:3:15
+   |
+LL | fn i(n{...,f #
+   |               ^ expected `:`
+
+error: expected one of `->`, `where`, or `{`, found `<eof>`
+  --> $DIR/issue-63135.rs:3:15
+   |
+LL | fn i(n{...,f #
+   |               ^ expected one of `->`, `where`, or `{` here
+
+error: aborting due to 6 previous errors
+