about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/ich/impls_ty.rs6
-rw-r--r--src/librustc/mir/interpret/error.rs55
-rw-r--r--src/librustc_mir/interpret/eval_context.rs15
-rw-r--r--src/test/ui/infinite/infinite-recursion-const-fn.stderr102
4 files changed, 100 insertions, 78 deletions
diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs
index 9a6c23703bb..64685446e8f 100644
--- a/src/librustc/ich/impls_ty.rs
+++ b/src/librustc/ich/impls_ty.rs
@@ -389,10 +389,10 @@ impl_stable_hash_for!(enum mir::interpret::ErrorHandled {
     TooGeneric
 });
 
-impl_stable_hash_for!(struct mir::interpret::FrameInfo {
-    span,
+impl_stable_hash_for!(struct mir::interpret::FrameInfo<'tcx> {
+    call_site,
     lint_root,
-    location
+    instance
 });
 
 impl_stable_hash_for!(struct ty::ClosureSubsts<'tcx> { substs });
diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs
index bf678db51c9..f1c95e0f000 100644
--- a/src/librustc/mir/interpret/error.rs
+++ b/src/librustc/mir/interpret/error.rs
@@ -10,8 +10,9 @@
 
 use std::{fmt, env};
 
+use hir::map::definitions::DefPathData;
 use mir;
-use ty::{Ty, layout};
+use ty::{self, Ty, layout};
 use ty::layout::{Size, Align, LayoutError};
 use rustc_target::spec::abi::Abi;
 
@@ -19,11 +20,10 @@ use super::{Pointer, InboundsCheck, ScalarMaybeUndef};
 
 use backtrace::Backtrace;
 
-use ty;
 use ty::query::TyCtxtAt;
 use errors::DiagnosticBuilder;
 
-use syntax_pos::Span;
+use syntax_pos::{Pos, Span};
 use syntax::ast;
 use syntax::symbol::Symbol;
 
@@ -52,16 +52,35 @@ pub type ConstEvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, ErrorHandled>;
 pub struct ConstEvalErr<'tcx> {
     pub span: Span,
     pub error: ::mir::interpret::EvalErrorKind<'tcx, u64>,
-    pub stacktrace: Vec<FrameInfo>,
+    pub stacktrace: Vec<FrameInfo<'tcx>>,
 }
 
 #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
-pub struct FrameInfo {
-    pub span: Span,
-    pub location: String,
+pub struct FrameInfo<'tcx> {
+    pub call_site: Span, // this span is in the caller!
+    pub instance: ty::Instance<'tcx>,
     pub lint_root: Option<ast::NodeId>,
 }
 
+impl<'tcx> fmt::Display for FrameInfo<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        ty::tls::with(|tcx| {
+            if tcx.def_key(self.instance.def_id()).disambiguated_data.data
+                == DefPathData::ClosureExpr
+            {
+                write!(f, "inside call to closure")?;
+            } else {
+                write!(f, "inside call to `{}`", self.instance)?;
+            }
+            if !self.call_site.is_dummy() {
+                let lo = tcx.sess.source_map().lookup_char_pos_adj(self.call_site.lo());
+                write!(f, " at {}:{}:{}", lo.filename, lo.line, lo.col.to_usize() + 1)?;
+            }
+            Ok(())
+        })
+    }
+}
+
 impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
     pub fn struct_error(&self,
         tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
@@ -135,8 +154,13 @@ impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
             struct_error(tcx, message)
         };
         err.span_label(self.span, self.error.to_string());
-        for FrameInfo { span, location, .. } in &self.stacktrace {
-            err.span_label(*span, format!("inside call to `{}`", location));
+        // Skip the last, which is just the environment of the constant.  The stacktrace
+        // is sometimes empty because we create "fake" eval contexts in CTFE to do work
+        // on constant values.
+        if self.stacktrace.len() > 0 {
+            for frame_info in &self.stacktrace[..self.stacktrace.len()-1] {
+                err.span_label(frame_info.call_site, frame_info.to_string());
+            }
         }
         Ok(err)
     }
@@ -172,16 +196,23 @@ fn print_backtrace(backtrace: &mut Backtrace) -> String {
     write!(trace_text, "backtrace frames: {}\n", backtrace.frames().len()).unwrap();
     'frames: for (i, frame) in backtrace.frames().iter().enumerate() {
         if frame.symbols().is_empty() {
-            write!(trace_text, "{}: no symbols\n", i).unwrap();
+            write!(trace_text, "  {}: no symbols\n", i).unwrap();
         }
+        let mut first = true;
         for symbol in frame.symbols() {
-            write!(trace_text, "{}: ", i).unwrap();
+            if first {
+                write!(trace_text, "  {}: ", i).unwrap();
+                first = false;
+            } else {
+                let len = i.to_string().len();
+                write!(trace_text, "  {}  ", " ".repeat(len)).unwrap();
+            }
             if let Some(name) = symbol.name() {
                 write!(trace_text, "{}\n", name).unwrap();
             } else {
                 write!(trace_text, "<unknown>\n").unwrap();
             }
-            write!(trace_text, "\tat ").unwrap();
+            write!(trace_text, "           at ").unwrap();
             if let Some(file_path) = symbol.filename() {
                 write!(trace_text, "{}", file_path.display()).unwrap();
             } else {
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index e6267012dc2..dbda506d115 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -14,7 +14,6 @@ use std::mem;
 use syntax::source_map::{self, Span, DUMMY_SP};
 use rustc::hir::def_id::DefId;
 use rustc::hir::def::Def;
-use rustc::hir::map::definitions::DefPathData;
 use rustc::mir;
 use rustc::ty::layout::{
     self, Size, Align, HasDataLayout, LayoutOf, TyLayout
@@ -654,11 +653,10 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
         }
     }
 
-    pub fn generate_stacktrace(&self, explicit_span: Option<Span>) -> Vec<FrameInfo> {
+    pub fn generate_stacktrace(&self, explicit_span: Option<Span>) -> Vec<FrameInfo<'tcx>> {
         let mut last_span = None;
         let mut frames = Vec::new();
-        // skip 1 because the last frame is just the environment of the constant
-        for &Frame { instance, span, mir, block, stmt, .. } in self.stack().iter().skip(1).rev() {
+        for &Frame { instance, span, mir, block, stmt, .. } in self.stack().iter().rev() {
             // make sure we don't emit frames that are duplicates of the previous
             if explicit_span == Some(span) {
                 last_span = Some(span);
@@ -671,13 +669,6 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
             } else {
                 last_span = Some(span);
             }
-            let location = if self.tcx.def_key(instance.def_id()).disambiguated_data.data
-                == DefPathData::ClosureExpr
-            {
-                "closure".to_owned()
-            } else {
-                instance.to_string()
-            };
             let block = &mir.basic_blocks()[block];
             let source_info = if stmt < block.statements.len() {
                 block.statements[stmt].source_info
@@ -688,7 +679,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
                 mir::ClearCrossCrate::Set(ref ivs) => Some(ivs[source_info.scope].lint_root),
                 mir::ClearCrossCrate::Clear => None,
             };
-            frames.push(FrameInfo { span, location, lint_root });
+            frames.push(FrameInfo { call_site: span, instance, lint_root });
         }
         trace!("generate stacktrace: {:#?}, {:?}", frames, explicit_span);
         frames
diff --git a/src/test/ui/infinite/infinite-recursion-const-fn.stderr b/src/test/ui/infinite/infinite-recursion-const-fn.stderr
index ef35bb6d98d..4246ec2dad3 100644
--- a/src/test/ui/infinite/infinite-recursion-const-fn.stderr
+++ b/src/test/ui/infinite/infinite-recursion-const-fn.stderr
@@ -5,61 +5,61 @@ LL | const fn a() -> usize { b() } //~ ERROR evaluation of constant value failed
    |                         ^^^
    |                         |
    |                         reached the configured maximum number of stack frames
-   |                         inside call to `b`
+   |                         inside call to `b` at $DIR/infinite-recursion-const-fn.rs:13:25
 LL | const fn b() -> usize { a() }
    |                         ---
    |                         |
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
-   |                         inside call to `a`
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
+   |                         inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
 LL | const ARR: [i32; a()] = [5; 6];
-   |                  --- inside call to `a`
+   |                  --- inside call to `a` at $DIR/infinite-recursion-const-fn.rs:15:18
 
 error: aborting due to previous error