about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>2018-01-31 10:39:30 +0100
committerOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>2018-03-08 08:34:16 +0100
commitbd03371f711adcb7724c939ea053f4090e87c16f (patch)
treeb052b81c10cad02d120d6c6be07e13bb215fbf63
parent8c53d54b98edd77e32fbf4f4fd27d312b251ec6b (diff)
downloadrust-bd03371f711adcb7724c939ea053f4090e87c16f.tar.gz
rust-bd03371f711adcb7724c939ea053f4090e87c16f.zip
Add stack traces to miri errors
-rw-r--r--src/librustc/ich/impls_ty.rs14
-rw-r--r--src/librustc/middle/const_val.rs34
-rw-r--r--src/librustc/mir/interpret/error.rs9
-rw-r--r--src/librustc/traits/error_reporting.rs2
-rw-r--r--src/librustc/traits/fulfill.rs2
-rw-r--r--src/librustc/ty/structural_impls.rs10
6 files changed, 43 insertions, 28 deletions
diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs
index 72bc5af3b7e..a398549f359 100644
--- a/src/librustc/ich/impls_ty.rs
+++ b/src/librustc/ich/impls_ty.rs
@@ -440,6 +440,11 @@ impl_stable_hash_for!(struct ::middle::const_val::ConstEvalErr<'tcx> {
     kind
 });
 
+impl_stable_hash_for!(struct ::middle::const_val::FrameInfo {
+    span,
+    location
+});
+
 impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
 for ::middle::const_val::ErrKind<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
@@ -468,7 +473,10 @@ for ::middle::const_val::ErrKind<'gcx> {
             LayoutError(ref layout_error) => {
                 layout_error.hash_stable(hcx, hasher);
             }
-            Miri(ref err) => err.hash_stable(hcx, hasher),
+            Miri(ref err, ref trace) => {
+                err.hash_stable(hcx, hasher);
+                trace.hash_stable(hcx, hasher);
+            },
         }
     }
 }
@@ -489,9 +497,9 @@ for ::mir::interpret::EvalError<'gcx> {
                                           hasher: &mut StableHasher<W>) {
         use mir::interpret::EvalErrorKind::*;
 
-        mem::discriminant(&*self.kind).hash_stable(hcx, hasher);
+        mem::discriminant(&self.kind).hash_stable(hcx, hasher);
 
-        match *self.kind {
+        match self.kind {
             DanglingPointerDeref |
             DoubleFree |
             InvalidMemoryAccess |
diff --git a/src/librustc/middle/const_val.rs b/src/librustc/middle/const_val.rs
index c987ed0ea5d..d6d23c5cad8 100644
--- a/src/librustc/middle/const_val.rs
+++ b/src/librustc/middle/const_val.rs
@@ -19,6 +19,7 @@ use graphviz::IntoCow;
 use syntax_pos::Span;
 
 use std::borrow::Cow;
+use std::rc::Rc;
 
 pub type EvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, ConstEvalErr<'tcx>>;
 
@@ -51,7 +52,7 @@ impl<'tcx> ConstVal<'tcx> {
 #[derive(Clone, Debug)]
 pub struct ConstEvalErr<'tcx> {
     pub span: Span,
-    pub kind: ErrKind<'tcx>,
+    pub kind: Rc<ErrKind<'tcx>>,
 }
 
 #[derive(Clone, Debug)]
@@ -66,13 +67,13 @@ pub enum ErrKind<'tcx> {
 
     TypeckError,
     CheckMatchError,
-    Miri(::mir::interpret::EvalError<'tcx>),
+    Miri(::mir::interpret::EvalError<'tcx>, Vec<FrameInfo>),
 }
 
-impl<'tcx> From<::mir::interpret::EvalError<'tcx>> for ErrKind<'tcx> {
-    fn from(err: ::mir::interpret::EvalError<'tcx>) -> ErrKind<'tcx> {
-        ErrKind::Miri(err)
-    }
+#[derive(Clone, Debug)]
+pub struct FrameInfo {
+    pub span: Span,
+    pub location: String,
 }
 
 impl<'tcx> From<ConstMathErr> for ErrKind<'tcx> {
@@ -85,21 +86,23 @@ impl<'tcx> From<ConstMathErr> for ErrKind<'tcx> {
 }
 
 #[derive(Clone, Debug)]
-pub enum ConstEvalErrDescription<'a> {
+pub enum ConstEvalErrDescription<'a, 'tcx: 'a> {
     Simple(Cow<'a, str>),
+    Backtrace(&'a ::mir::interpret::EvalError<'tcx>, &'a [FrameInfo]),
 }
 
-impl<'a> ConstEvalErrDescription<'a> {
+impl<'a, 'tcx> ConstEvalErrDescription<'a, 'tcx> {
     /// Return a one-line description of the error, for lints and such
     pub fn into_oneline(self) -> Cow<'a, str> {
         match self {
             ConstEvalErrDescription::Simple(simple) => simple,
+            ConstEvalErrDescription::Backtrace(miri, _) => format!("{}", miri).into_cow(),
         }
     }
 }
 
 impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
-    pub fn description(&self) -> ConstEvalErrDescription {
+    pub fn description(&'a self) -> ConstEvalErrDescription<'a, 'tcx> {
         use self::ErrKind::*;
         use self::ConstEvalErrDescription::*;
 
@@ -110,7 +113,7 @@ impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
             })
         }
 
-        match self.kind {
+        match *self.kind {
             NonConstPath        => simple!("non-constant path in constant expression"),
             UnimplementedConstVal(what) =>
                 simple!("unimplemented constant expression: {}", what),
@@ -124,8 +127,7 @@ impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
 
             TypeckError => simple!("type-checking failed"),
             CheckMatchError => simple!("match-checking failed"),
-            // FIXME: report a full backtrace
-            Miri(ref err) => simple!("{}", err),
+            Miri(ref err, ref trace) => Backtrace(err, trace),
         }
     }
 
@@ -150,6 +152,12 @@ impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
             ConstEvalErrDescription::Simple(message) => {
                 diag.span_label(self.span, message);
             }
+            ConstEvalErrDescription::Backtrace(miri, frames) => {
+                diag.span_label(self.span, format!("{}", miri));
+                for frame in frames {
+                    diag.span_label(frame.span, format!("inside call to {}", frame.location));
+                }
+            }
         }
 
         if !primary_span.contains(self.span) {
@@ -163,7 +171,7 @@ impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
         primary_span: Span,
         primary_kind: &str)
     {
-        match self.kind {
+        match *self.kind {
             ErrKind::TypeckError | ErrKind::CheckMatchError => return,
             _ => {}
         }
diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs
index 3e8aeaff57e..90d10df1515 100644
--- a/src/librustc/mir/interpret/error.rs
+++ b/src/librustc/mir/interpret/error.rs
@@ -1,6 +1,5 @@
 use std::error::Error;
 use std::{fmt, env};
-use std::rc::Rc;
 
 use mir;
 use ty::{FnSig, Ty, layout};
@@ -15,7 +14,7 @@ use backtrace::Backtrace;
 
 #[derive(Debug, Clone)]
 pub struct EvalError<'tcx> {
-    pub kind: Rc<EvalErrorKind<'tcx>>,
+    pub kind: EvalErrorKind<'tcx>,
     pub backtrace: Option<Backtrace>,
 }
 
@@ -26,7 +25,7 @@ impl<'tcx> From<EvalErrorKind<'tcx>> for EvalError<'tcx> {
             _ => None
         };
         EvalError {
-            kind: Rc::new(kind),
+            kind,
             backtrace,
         }
     }
@@ -132,7 +131,7 @@ pub type EvalResult<'tcx, T = ()> = Result<T, EvalError<'tcx>>;
 impl<'tcx> Error for EvalError<'tcx> {
     fn description(&self) -> &str {
         use self::EvalErrorKind::*;
-        match *self.kind {
+        match self.kind {
             MachineError(ref inner) => inner,
             FunctionPointerTyMismatch(..) =>
                 "tried to call a function through a function pointer of a different type",
@@ -253,7 +252,7 @@ impl<'tcx> Error for EvalError<'tcx> {
 impl<'tcx> fmt::Display for EvalError<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         use self::EvalErrorKind::*;
-        match *self.kind {
+        match self.kind {
             PointerOutOfBounds { ptr, access, allocation_size } => {
                 write!(f, "{} at offset {}, outside bounds of allocation {} which has size {}",
                        if access { "memory access" } else { "pointer computed" },
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index 2e554aff13e..cd2d0d7e2a0 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -775,7 +775,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
             }
 
             ConstEvalFailure(ref err) => {
-                if let ::middle::const_val::ErrKind::TypeckError = err.kind {
+                if let ::middle::const_val::ErrKind::TypeckError = *err.kind {
                     return;
                 }
                 err.struct_error(self.tcx, span, "constant expression")
diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs
index 5c082b0610f..15925a19d75 100644
--- a/src/librustc/traits/fulfill.rs
+++ b/src/librustc/traits/fulfill.rs
@@ -536,7 +536,7 @@ fn process_predicate<'a, 'gcx, 'tcx>(
                             } else {
                                 Err(CodeSelectionError(ConstEvalFailure(ConstEvalErr {
                                     span: obligation.cause.span,
-                                    kind: ErrKind::UnimplementedConstVal("could not resolve"),
+                                    kind: ErrKind::UnimplementedConstVal("could not resolve").into(),
                                 })))
                             }
                         },
diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs
index 4e1f3664d7f..c1a4f5ef458 100644
--- a/src/librustc/ty/structural_impls.rs
+++ b/src/librustc/ty/structural_impls.rs
@@ -578,10 +578,10 @@ impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> {
 impl<'a, 'tcx> Lift<'tcx> for ConstEvalErr<'a> {
     type Lifted = ConstEvalErr<'tcx>;
     fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
-        tcx.lift(&self.kind).map(|kind| {
+        tcx.lift(&*self.kind).map(|kind| {
             ConstEvalErr {
                 span: self.span,
-                kind,
+                kind: Rc::new(kind),
             }
         })
     }
@@ -591,7 +591,7 @@ impl<'a, 'tcx> Lift<'tcx> for interpret::EvalError<'a> {
     type Lifted = interpret::EvalError<'tcx>;
     fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
         use ::mir::interpret::EvalErrorKind::*;
-        let kind = match *self.kind {
+        let kind = match self.kind {
             MachineError(ref err) => MachineError(err.clone()),
             FunctionPointerTyMismatch(a, b) => FunctionPointerTyMismatch(
                 tcx.lift(&a)?,
@@ -691,7 +691,7 @@ impl<'a, 'tcx> Lift<'tcx> for interpret::EvalError<'a> {
             TypeckError => TypeckError,
         };
         Some(interpret::EvalError {
-            kind: Rc::new(kind),
+            kind: kind,
             backtrace: self.backtrace.clone(),
         })
     }
@@ -714,7 +714,7 @@ impl<'a, 'tcx> Lift<'tcx> for const_val::ErrKind<'a> {
 
             TypeckError => TypeckError,
             CheckMatchError => CheckMatchError,
-            Miri(ref e) => return tcx.lift(e).map(Miri),
+            Miri(ref e, ref frames) => return tcx.lift(e).map(|e| Miri(e, frames.clone())),
         })
     }
 }