Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Miri backtrace improvements #55970

Merged
merged 4 commits into from
Nov 19, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/librustc/ich/impls_ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -387,10 +387,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 });
Expand Down
55 changes: 43 additions & 12 deletions src/librustc/mir/interpret/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,20 @@

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;

use super::{Pointer, Scalar};

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;

Expand Down Expand Up @@ -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>,
Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -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 {
Expand Down
15 changes: 3 additions & 12 deletions src/librustc_mir/interpret/eval_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand All @@ -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
Expand All @@ -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
Expand Down
102 changes: 51 additions & 51 deletions src/test/ui/infinite/infinite-recursion-const-fn.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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
oli-obk marked this conversation as resolved.
Show resolved Hide resolved
| 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

Expand Down