Skip to content

Commit 34ab7ce

Browse files
authored
Rollup merge of rust-lang#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
2 parents 00a84e3 + 62cf9ab commit 34ab7ce

File tree

4 files changed

+100
-78
lines changed

4 files changed

+100
-78
lines changed

src/librustc/ich/impls_ty.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -389,10 +389,10 @@ impl_stable_hash_for!(enum mir::interpret::ErrorHandled {
389389
TooGeneric
390390
});
391391

392-
impl_stable_hash_for!(struct mir::interpret::FrameInfo {
393-
span,
392+
impl_stable_hash_for!(struct mir::interpret::FrameInfo<'tcx> {
393+
call_site,
394394
lint_root,
395-
location
395+
instance
396396
});
397397

398398
impl_stable_hash_for!(struct ty::ClosureSubsts<'tcx> { substs });

src/librustc/mir/interpret/error.rs

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,20 @@
1010

1111
use std::{fmt, env};
1212

13+
use hir::map::definitions::DefPathData;
1314
use mir;
14-
use ty::{Ty, layout};
15+
use ty::{self, Ty, layout};
1516
use ty::layout::{Size, Align, LayoutError};
1617
use rustc_target::spec::abi::Abi;
1718

1819
use super::{Pointer, InboundsCheck, ScalarMaybeUndef};
1920

2021
use backtrace::Backtrace;
2122

22-
use ty;
2323
use ty::query::TyCtxtAt;
2424
use errors::DiagnosticBuilder;
2525

26-
use syntax_pos::Span;
26+
use syntax_pos::{Pos, Span};
2727
use syntax::ast;
2828
use syntax::symbol::Symbol;
2929

@@ -52,16 +52,35 @@ pub type ConstEvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, ErrorHandled>;
5252
pub struct ConstEvalErr<'tcx> {
5353
pub span: Span,
5454
pub error: ::mir::interpret::EvalErrorKind<'tcx, u64>,
55-
pub stacktrace: Vec<FrameInfo>,
55+
pub stacktrace: Vec<FrameInfo<'tcx>>,
5656
}
5757

5858
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
59-
pub struct FrameInfo {
60-
pub span: Span,
61-
pub location: String,
59+
pub struct FrameInfo<'tcx> {
60+
pub call_site: Span, // this span is in the caller!
61+
pub instance: ty::Instance<'tcx>,
6262
pub lint_root: Option<ast::NodeId>,
6363
}
6464

65+
impl<'tcx> fmt::Display for FrameInfo<'tcx> {
66+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67+
ty::tls::with(|tcx| {
68+
if tcx.def_key(self.instance.def_id()).disambiguated_data.data
69+
== DefPathData::ClosureExpr
70+
{
71+
write!(f, "inside call to closure")?;
72+
} else {
73+
write!(f, "inside call to `{}`", self.instance)?;
74+
}
75+
if !self.call_site.is_dummy() {
76+
let lo = tcx.sess.source_map().lookup_char_pos_adj(self.call_site.lo());
77+
write!(f, " at {}:{}:{}", lo.filename, lo.line, lo.col.to_usize() + 1)?;
78+
}
79+
Ok(())
80+
})
81+
}
82+
}
83+
6584
impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
6685
pub fn struct_error(&self,
6786
tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
@@ -135,8 +154,13 @@ impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
135154
struct_error(tcx, message)
136155
};
137156
err.span_label(self.span, self.error.to_string());
138-
for FrameInfo { span, location, .. } in &self.stacktrace {
139-
err.span_label(*span, format!("inside call to `{}`", location));
157+
// Skip the last, which is just the environment of the constant. The stacktrace
158+
// is sometimes empty because we create "fake" eval contexts in CTFE to do work
159+
// on constant values.
160+
if self.stacktrace.len() > 0 {
161+
for frame_info in &self.stacktrace[..self.stacktrace.len()-1] {
162+
err.span_label(frame_info.call_site, frame_info.to_string());
163+
}
140164
}
141165
Ok(err)
142166
}
@@ -172,16 +196,23 @@ fn print_backtrace(backtrace: &mut Backtrace) -> String {
172196
write!(trace_text, "backtrace frames: {}\n", backtrace.frames().len()).unwrap();
173197
'frames: for (i, frame) in backtrace.frames().iter().enumerate() {
174198
if frame.symbols().is_empty() {
175-
write!(trace_text, "{}: no symbols\n", i).unwrap();
199+
write!(trace_text, " {}: no symbols\n", i).unwrap();
176200
}
201+
let mut first = true;
177202
for symbol in frame.symbols() {
178-
write!(trace_text, "{}: ", i).unwrap();
203+
if first {
204+
write!(trace_text, " {}: ", i).unwrap();
205+
first = false;
206+
} else {
207+
let len = i.to_string().len();
208+
write!(trace_text, " {} ", " ".repeat(len)).unwrap();
209+
}
179210
if let Some(name) = symbol.name() {
180211
write!(trace_text, "{}\n", name).unwrap();
181212
} else {
182213
write!(trace_text, "<unknown>\n").unwrap();
183214
}
184-
write!(trace_text, "\tat ").unwrap();
215+
write!(trace_text, " at ").unwrap();
185216
if let Some(file_path) = symbol.filename() {
186217
write!(trace_text, "{}", file_path.display()).unwrap();
187218
} else {

src/librustc_mir/interpret/eval_context.rs

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ use std::mem;
1414
use syntax::source_map::{self, Span, DUMMY_SP};
1515
use rustc::hir::def_id::DefId;
1616
use rustc::hir::def::Def;
17-
use rustc::hir::map::definitions::DefPathData;
1817
use rustc::mir;
1918
use rustc::ty::layout::{
2019
self, Size, Align, HasDataLayout, LayoutOf, TyLayout
@@ -654,11 +653,10 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
654653
}
655654
}
656655

657-
pub fn generate_stacktrace(&self, explicit_span: Option<Span>) -> Vec<FrameInfo> {
656+
pub fn generate_stacktrace(&self, explicit_span: Option<Span>) -> Vec<FrameInfo<'tcx>> {
658657
let mut last_span = None;
659658
let mut frames = Vec::new();
660-
// skip 1 because the last frame is just the environment of the constant
661-
for &Frame { instance, span, mir, block, stmt, .. } in self.stack().iter().skip(1).rev() {
659+
for &Frame { instance, span, mir, block, stmt, .. } in self.stack().iter().rev() {
662660
// make sure we don't emit frames that are duplicates of the previous
663661
if explicit_span == Some(span) {
664662
last_span = Some(span);
@@ -671,13 +669,6 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
671669
} else {
672670
last_span = Some(span);
673671
}
674-
let location = if self.tcx.def_key(instance.def_id()).disambiguated_data.data
675-
== DefPathData::ClosureExpr
676-
{
677-
"closure".to_owned()
678-
} else {
679-
instance.to_string()
680-
};
681672
let block = &mir.basic_blocks()[block];
682673
let source_info = if stmt < block.statements.len() {
683674
block.statements[stmt].source_info
@@ -688,7 +679,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
688679
mir::ClearCrossCrate::Set(ref ivs) => Some(ivs[source_info.scope].lint_root),
689680
mir::ClearCrossCrate::Clear => None,
690681
};
691-
frames.push(FrameInfo { span, location, lint_root });
682+
frames.push(FrameInfo { call_site: span, instance, lint_root });
692683
}
693684
trace!("generate stacktrace: {:#?}, {:?}", frames, explicit_span);
694685
frames

src/test/ui/infinite/infinite-recursion-const-fn.stderr

Lines changed: 51 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -5,61 +5,61 @@ LL | const fn a() -> usize { b() } //~ ERROR evaluation of constant value failed
55
| ^^^
66
| |
77
| reached the configured maximum number of stack frames
8-
| inside call to `b`
8+
| inside call to `b` at $DIR/infinite-recursion-const-fn.rs:13:25
99
LL | const fn b() -> usize { a() }
1010
| ---
1111
| |
12-
| inside call to `a`
13-
| inside call to `a`
14-
| inside call to `a`
15-
| inside call to `a`
16-
| inside call to `a`
17-
| inside call to `a`
18-
| inside call to `a`
19-
| inside call to `a`
20-
| inside call to `a`
21-
| inside call to `a`
22-
| inside call to `a`
23-
| inside call to `a`
24-
| inside call to `a`
25-
| inside call to `a`
26-
| inside call to `a`
27-
| inside call to `a`
28-
| inside call to `a`
29-
| inside call to `a`
30-
| inside call to `a`
31-
| inside call to `a`
32-
| inside call to `a`
33-
| inside call to `a`
34-
| inside call to `a`
35-
| inside call to `a`
36-
| inside call to `a`
37-
| inside call to `a`
38-
| inside call to `a`
39-
| inside call to `a`
40-
| inside call to `a`
41-
| inside call to `a`
42-
| inside call to `a`
43-
| inside call to `a`
44-
| inside call to `a`
45-
| inside call to `a`
46-
| inside call to `a`
47-
| inside call to `a`
48-
| inside call to `a`
49-
| inside call to `a`
50-
| inside call to `a`
51-
| inside call to `a`
52-
| inside call to `a`
53-
| inside call to `a`
54-
| inside call to `a`
55-
| inside call to `a`
56-
| inside call to `a`
57-
| inside call to `a`
58-
| inside call to `a`
59-
| inside call to `a`
60-
| inside call to `a`
12+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
13+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
14+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
15+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
16+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
17+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
18+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
19+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
20+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
21+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
22+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
23+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
24+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
25+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
26+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
27+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
28+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
29+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
30+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
31+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
32+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
33+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
34+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
35+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
36+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
37+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
38+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
39+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
40+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
41+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
42+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
43+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
44+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
45+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
46+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
47+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
48+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
49+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
50+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
51+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
52+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
53+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
54+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
55+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
56+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
57+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
58+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
59+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
60+
| inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25
6161
LL | const ARR: [i32; a()] = [5; 6];
62-
| --- inside call to `a`
62+
| --- inside call to `a` at $DIR/infinite-recursion-const-fn.rs:15:18
6363

6464
error: aborting due to previous error
6565

0 commit comments

Comments
 (0)