miri: backtraces with instances

This commit is contained in:
Ralf Jung 2018-11-14 17:25:06 +01:00
parent 126a0e2aad
commit 57a7c85f93
3 changed files with 31 additions and 21 deletions

View File

@ -387,10 +387,10 @@ fn hash_stable<W: StableHasherResult>(
TooGeneric
});
impl_stable_hash_for!(struct mir::interpret::FrameInfo {
impl_stable_hash_for!(struct mir::interpret::FrameInfo<'tcx> {
span,
lint_root,
location
instance
});
impl_stable_hash_for!(struct ty::ClosureSubsts<'tcx> { substs });

View File

@ -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,7 +20,6 @@
use backtrace::Backtrace;
use ty;
use ty::query::TyCtxtAt;
use errors::DiagnosticBuilder;
@ -52,16 +52,30 @@ pub fn assert_reported(self) {
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 struct FrameInfo<'tcx> {
pub span: Span,
pub location: String,
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)
}
})
}
}
impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
pub fn struct_error(&self,
tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
@ -135,8 +149,13 @@ fn struct_generic(
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.span, frame_info.to_string());
}
}
Ok(err)
}

View File

@ -14,7 +14,6 @@
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 @@ pub fn dump_place(&self, place: Place<M::PointerTag>) {
}
}
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 @@ pub fn generate_stacktrace(&self, explicit_span: Option<Span>) -> Vec<FrameInfo>
} 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 @@ pub fn generate_stacktrace(&self, explicit_span: Option<Span>) -> Vec<FrameInfo>
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 { span, instance, lint_root });
}
trace!("generate stacktrace: {:#?}, {:?}", frames, explicit_span);
frames