diff options
| author | Pietro Albini <pietro@pietroalbini.org> | 2018-11-18 23:24:53 +0100 |
|---|---|---|
| committer | kennytm <kennytm@gmail.com> | 2018-11-19 22:06:29 +0800 |
| commit | cc6473d342ca017a983ff5805a4fde052b7301d5 (patch) | |
| tree | a16d2007f74fd83eb55f77da0e0fe147133fe18c /src/librustc/mir/interpret | |
| parent | 6ecbb05d76daa3d49ef3aab0fe4ba1406fd7fe7f (diff) | |
| parent | 62cf9abcf6611c598894e9a8abac6c54a72d862d (diff) | |
| download | rust-cc6473d342ca017a983ff5805a4fde052b7301d5.tar.gz rust-cc6473d342ca017a983ff5805a4fde052b7301d5.zip | |
Rollup merge of #55970 - RalfJung:miri-backtrace, r=@oli-obk
Miri backtrace improvements
Nicer pretty-printing of the `RUST_CTFE_BACKTRACE`-backtraces:
```
0: backtrace::backtrace::libunwind::trace::hc410fcb66fe85b11
at /home/r/.cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.9/src/backtrace/libunwind.rs:53
backtrace::backtrace::trace::h2106294a22648407
at /home/r/.cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.9/src/backtrace/mod.rs:42
1: backtrace::capture::Backtrace::new_unresolved::h5d8d98b993d092ba
at /home/r/.cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.9/src/capture.rs:88
2: <rustc::mir::interpret::error::EvalError<'tcx> as core::convert::From<rustc::mir::interpret::error::EvalErrorKind<'tcx, u64>>>::from::h6355269b2a661412
at librustc/mir/interpret/error.rs:236
3: <T as core::convert::Into<U>>::into::h70fcb917509539bd
at /home/r/src/rust/rustc.2/src/libcore/convert.rs:455
4: <rustc_mir::interpret::eval_context::EvalContext<'a, 'mir, 'tcx, miri::Evaluator<'tcx>> as miri::fn_call::EvalContextExt<'tcx, 'mir>>::emulate_foreign_item::h9cde0e3ce7455a4a
at src/fn_call.rs:292
5: <rustc_mir::interpret::eval_context::EvalContext<'a, 'mir, 'tcx, miri::Evaluator<'tcx>> as miri::fn_call::EvalContextExt<'tcx, 'mir>>::find_fn::h83f89524b9d1a49a
at src/fn_call.rs:74
6: <miri::Evaluator<'tcx> as rustc_mir::interpret::machine::Machine<'a, 'mir, 'tcx>>::find_fn::hf9980473c4775f0c
at src/lib.rs:345
rustc_mir::interpret::terminator::<impl rustc_mir::interpret::eval_context::EvalContext<'a, 'mir, 'tcx, M>>::eval_fn_call::h401dec4a687f96e9
at /home/r/src/rust/rustc.2/src/librustc_mir/interpret/terminator.rs:285
```
Indentation is now consistent with `RUST_BACKTRACE`, and the frame number is not repeated when there are multiple symbols for a frame.
Also preserve the `ty::Instance` for the internal backtrace (showing which frames in the user code where on the interpreter stack when the error happened), used by miri to avoid printing spans for libstd internals:
```
error[E0080]: constant evaluation error: the evaluated program panicked
--> /home/r/src/rust/rustc.2/src/libstd/panicking.rs:525:9
|
525 | __rust_start_panic(obj as usize)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked
|
= note: inside call to `std::panicking::rust_panic` at /home/r/src/rust/rustc.2/src/libstd/panicking.rs:496:5
= note: inside call to `std::panicking::rust_panic_with_hook` at /home/r/src/rust/rustc.2/src/libstd/panicking.rs:390:5
= note: inside call to `std::panicking::continue_panic_fmt` at /home/r/src/rust/rustc.2/src/libstd/panicking.rs:345:5
note: inside call to `std::rt::begin_panic_fmt` at <::std::macros::panic macros>:8:1
--> tests/compile-fail/panic.rs:4:5
|
4 | assert_eq!(5, 6);
| ^^^^^^^^^^^^^^^^^
= note: inside call to `main` at /home/r/src/rust/rustc.2/src/libstd/rt.rs:74:34
= note: inside call to closure at /home/r/src/rust/rustc.2/src/libstd/rt.rs:59:75
= note: inside call to closure at /home/r/src/rust/rustc.2/src/libstd/sys_common/backtrace.rs:136:5
= note: inside call to `std::sys_common::backtrace::__rust_begin_short_backtrace::<[closure@DefId(1/1:1913 ~ std[78f0]::rt[0]::lang_start_internal[0]::{{closure}}[0]::{{closure}}[0]) 0:&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe], i32>` at /home/r/src/rust/rustc.2/src/libstd/rt.rs:59:13
= note: inside call to closure at /home/r/src/rust/rustc.2/src/libstd/panicking.rs:310:40
= note: inside call to `std::panicking::try::do_call::<[closure@DefId(1/1:1912 ~ std[78f0]::rt[0]::lang_start_internal[0]::{{closure}}[0]) 0:&&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe], i32>` at /home/r/src/rust/rustc.2/src/libstd/panicking.rs:306:5
= note: inside call to `std::panicking::try::<i32, [closure@DefId(1/1:1912 ~ std[78f0]::rt[0]::lang_start_internal[0]::{{closure}}[0]) 0:&&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe]>` at /home/r/src/rust/rustc.2/src/libstd/panic.rs:398:9
= note: inside call to `std::panic::catch_unwind::<[closure@DefId(1/1:1912 ~ std[78f0]::rt[0]::lang_start_internal[0]::{{closure}}[0]) 0:&&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe], i32>` at /home/r/src/rust/rustc.2/src/libstd/rt.rs:58:25
= note: inside call to `std::rt::lang_start_internal` at /home/r/src/rust/rustc.2/src/libstd/rt.rs:74:5
= note: inside call to `std::rt::lang_start::<()>`
```
Also notice that we show filenames and line numbers here now.
r? @oli-obk
Diffstat (limited to 'src/librustc/mir/interpret')
| -rw-r--r-- | src/librustc/mir/interpret/error.rs | 55 |
1 files changed, 43 insertions, 12 deletions
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 { |
