rustc_errors: split macro backtrace rendering from <*macros> hacks.
This commit is contained in:
parent
442ae7f040
commit
8f286dbf27
3 changed files with 98 additions and 68 deletions
|
@ -32,7 +32,7 @@ impl Emitter for AnnotateSnippetEmitterWriter {
|
||||||
let mut children = diag.children.clone();
|
let mut children = diag.children.clone();
|
||||||
let (mut primary_span, suggestions) = self.primary_span_formatted(&diag);
|
let (mut primary_span, suggestions) = self.primary_span_formatted(&diag);
|
||||||
|
|
||||||
self.fix_multispans_in_std_macros(
|
self.render_multispans_macro_backtrace_and_fix_extern_macros(
|
||||||
&self.source_map,
|
&self.source_map,
|
||||||
&mut primary_span,
|
&mut primary_span,
|
||||||
&mut children,
|
&mut children,
|
||||||
|
|
|
@ -280,10 +280,7 @@ pub trait Emitter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This does a small "fix" for multispans by looking to see if it can find any that
|
fn render_multispans_macro_backtrace_and_fix_extern_macros(
|
||||||
// point directly at <*macros>. Since these are often difficult to read, this
|
|
||||||
// will change the span to point at the use site.
|
|
||||||
fn fix_multispans_in_std_macros(
|
|
||||||
&self,
|
&self,
|
||||||
source_map: &Option<Lrc<SourceMap>>,
|
source_map: &Option<Lrc<SourceMap>>,
|
||||||
span: &mut MultiSpan,
|
span: &mut MultiSpan,
|
||||||
|
@ -291,61 +288,64 @@ pub trait Emitter {
|
||||||
level: &Level,
|
level: &Level,
|
||||||
backtrace: bool,
|
backtrace: bool,
|
||||||
) {
|
) {
|
||||||
let mut spans_updated = self.fix_multispan_in_std_macros(source_map, span, backtrace);
|
self.render_multispans_macro_backtrace(source_map, span, children, backtrace);
|
||||||
for child in children.iter_mut() {
|
|
||||||
spans_updated |=
|
|
||||||
self.fix_multispan_in_std_macros(source_map, &mut child.span, backtrace);
|
|
||||||
}
|
|
||||||
let msg = if level == &Error {
|
|
||||||
"this error originates in a macro outside of the current crate \
|
|
||||||
(in Nightly builds, run with -Z external-macro-backtrace \
|
|
||||||
for more info)"
|
|
||||||
.to_string()
|
|
||||||
} else {
|
|
||||||
"this warning originates in a macro outside of the current crate \
|
|
||||||
(in Nightly builds, run with -Z external-macro-backtrace \
|
|
||||||
for more info)"
|
|
||||||
.to_string()
|
|
||||||
};
|
|
||||||
|
|
||||||
if spans_updated {
|
if !backtrace {
|
||||||
children.push(SubDiagnostic {
|
if self.fix_multispans_in_extern_macros(source_map, span, children) {
|
||||||
level: Level::Note,
|
let msg = if level == &Error {
|
||||||
message: vec![(msg, Style::NoStyle)],
|
"this error originates in a macro outside of the current crate \
|
||||||
span: MultiSpan::new(),
|
(in Nightly builds, run with -Z external-macro-backtrace \
|
||||||
render_span: None,
|
for more info)"
|
||||||
});
|
.to_string()
|
||||||
|
} else {
|
||||||
|
"this warning originates in a macro outside of the current crate \
|
||||||
|
(in Nightly builds, run with -Z external-macro-backtrace \
|
||||||
|
for more info)"
|
||||||
|
.to_string()
|
||||||
|
};
|
||||||
|
|
||||||
|
children.push(SubDiagnostic {
|
||||||
|
level: Level::Note,
|
||||||
|
message: vec![(msg, Style::NoStyle)],
|
||||||
|
span: MultiSpan::new(),
|
||||||
|
render_span: None,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This "fixes" MultiSpans that contain Spans that are pointing to locations inside of
|
fn render_multispans_macro_backtrace(
|
||||||
// <*macros>. Since these locations are often difficult to read, we move these Spans from
|
&self,
|
||||||
// <*macros> to their corresponding use site.
|
source_map: &Option<Lrc<SourceMap>>,
|
||||||
fn fix_multispan_in_std_macros(
|
span: &mut MultiSpan,
|
||||||
|
children: &mut Vec<SubDiagnostic>,
|
||||||
|
backtrace: bool,
|
||||||
|
) {
|
||||||
|
self.render_multispan_macro_backtrace(source_map, span, backtrace);
|
||||||
|
for child in children.iter_mut() {
|
||||||
|
self.render_multispan_macro_backtrace(source_map, &mut child.span, backtrace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_multispan_macro_backtrace(
|
||||||
&self,
|
&self,
|
||||||
source_map: &Option<Lrc<SourceMap>>,
|
source_map: &Option<Lrc<SourceMap>>,
|
||||||
span: &mut MultiSpan,
|
span: &mut MultiSpan,
|
||||||
always_backtrace: bool,
|
always_backtrace: bool,
|
||||||
) -> bool {
|
) {
|
||||||
let sm = match source_map {
|
let sm = match source_map {
|
||||||
Some(ref sm) => sm,
|
Some(ref sm) => sm,
|
||||||
None => return false,
|
None => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut before_after: Vec<(Span, Span)> = vec![];
|
|
||||||
let mut new_labels: Vec<(Span, String)> = vec![];
|
let mut new_labels: Vec<(Span, String)> = vec![];
|
||||||
|
|
||||||
// First, find all the spans in <*macros> and point instead at their use site
|
// First, find all the spans in <*macros> and point instead at their use site
|
||||||
for sp in span.primary_spans() {
|
for &sp in span.primary_spans() {
|
||||||
if sp.is_dummy() {
|
if sp.is_dummy() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let call_sp = sm.call_span_if_macro(*sp);
|
|
||||||
if call_sp != *sp && !always_backtrace {
|
|
||||||
before_after.push((*sp, call_sp));
|
|
||||||
}
|
|
||||||
let macro_backtrace: Vec<_> = sp.macro_backtrace().collect();
|
let macro_backtrace: Vec<_> = sp.macro_backtrace().collect();
|
||||||
let backtrace_len = macro_backtrace.len();
|
|
||||||
for (i, trace) in macro_backtrace.iter().rev().enumerate() {
|
for (i, trace) in macro_backtrace.iter().rev().enumerate() {
|
||||||
// Only show macro locations that are local
|
// Only show macro locations that are local
|
||||||
// and display them like a span_note
|
// and display them like a span_note
|
||||||
|
@ -358,13 +358,13 @@ pub trait Emitter {
|
||||||
format!(
|
format!(
|
||||||
"in this expansion of `{}`{}",
|
"in this expansion of `{}`{}",
|
||||||
trace.kind.descr(),
|
trace.kind.descr(),
|
||||||
if backtrace_len > 2 {
|
if macro_backtrace.len() > 2 {
|
||||||
// if backtrace_len == 1 it'll be pointed
|
// if macro_backtrace.len() == 1 it'll be
|
||||||
// at by "in this macro invocation"
|
// pointed at by "in this macro invocation"
|
||||||
format!(" (#{})", i + 1)
|
format!(" (#{})", i + 1)
|
||||||
} else {
|
} else {
|
||||||
String::new()
|
String::new()
|
||||||
}
|
},
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -377,13 +377,13 @@ pub trait Emitter {
|
||||||
trace.call_site,
|
trace.call_site,
|
||||||
format!(
|
format!(
|
||||||
"in this macro invocation{}",
|
"in this macro invocation{}",
|
||||||
if backtrace_len > 2 && always_backtrace {
|
if macro_backtrace.len() > 2 && always_backtrace {
|
||||||
// only specify order when the macro
|
// only specify order when the macro
|
||||||
// backtrace is multiple levels deep
|
// backtrace is multiple levels deep
|
||||||
format!(" (#{})", i + 1)
|
format!(" (#{})", i + 1)
|
||||||
} else {
|
} else {
|
||||||
String::new()
|
String::new()
|
||||||
}
|
},
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
if !always_backtrace {
|
if !always_backtrace {
|
||||||
|
@ -395,20 +395,58 @@ pub trait Emitter {
|
||||||
for (label_span, label_text) in new_labels {
|
for (label_span, label_text) in new_labels {
|
||||||
span.push_span_label(label_span, label_text);
|
span.push_span_label(label_span, label_text);
|
||||||
}
|
}
|
||||||
for sp_label in span.span_labels() {
|
}
|
||||||
if sp_label.span.is_dummy() {
|
|
||||||
continue;
|
// This does a small "fix" for multispans by looking to see if it can find any that
|
||||||
}
|
// point directly at <*macros>. Since these are often difficult to read, this
|
||||||
if sm.span_to_filename(sp_label.span.clone()).is_macros() && !always_backtrace {
|
// will change the span to point at the use site.
|
||||||
if let Some(use_site) = sp_label.span.macro_backtrace().last() {
|
fn fix_multispans_in_extern_macros(
|
||||||
before_after.push((sp_label.span, use_site.call_site));
|
&self,
|
||||||
}
|
source_map: &Option<Lrc<SourceMap>>,
|
||||||
}
|
span: &mut MultiSpan,
|
||||||
|
children: &mut Vec<SubDiagnostic>,
|
||||||
|
) -> bool {
|
||||||
|
let mut spans_updated = self.fix_multispan_in_extern_macros(source_map, span);
|
||||||
|
for child in children.iter_mut() {
|
||||||
|
spans_updated |= self.fix_multispan_in_extern_macros(source_map, &mut child.span);
|
||||||
}
|
}
|
||||||
|
spans_updated
|
||||||
|
}
|
||||||
|
|
||||||
|
// This "fixes" MultiSpans that contain Spans that are pointing to locations inside of
|
||||||
|
// <*macros>. Since these locations are often difficult to read, we move these Spans from
|
||||||
|
// <*macros> to their corresponding use site.
|
||||||
|
fn fix_multispan_in_extern_macros(
|
||||||
|
&self,
|
||||||
|
source_map: &Option<Lrc<SourceMap>>,
|
||||||
|
span: &mut MultiSpan,
|
||||||
|
) -> bool {
|
||||||
|
let sm = match source_map {
|
||||||
|
Some(ref sm) => sm,
|
||||||
|
None => return false,
|
||||||
|
};
|
||||||
|
|
||||||
|
// First, find all the spans in <*macros> and point instead at their use site
|
||||||
|
let replacements: Vec<(Span, Span)> = span
|
||||||
|
.primary_spans()
|
||||||
|
.iter()
|
||||||
|
.copied()
|
||||||
|
.chain(span.span_labels().iter().map(|sp_label| sp_label.span))
|
||||||
|
.filter_map(|sp| {
|
||||||
|
if !sp.is_dummy() && sm.span_to_filename(sp).is_macros() {
|
||||||
|
let maybe_callsite = sp.source_callsite();
|
||||||
|
if sp != maybe_callsite {
|
||||||
|
return Some((sp, maybe_callsite));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
// After we have them, make sure we replace these 'bad' def sites with their use sites
|
// After we have them, make sure we replace these 'bad' def sites with their use sites
|
||||||
let spans_updated = !before_after.is_empty();
|
let spans_updated = !replacements.is_empty();
|
||||||
for (before, after) in before_after {
|
for (from, to) in replacements {
|
||||||
span.replace(before, after);
|
span.replace(from, to);
|
||||||
}
|
}
|
||||||
|
|
||||||
spans_updated
|
spans_updated
|
||||||
|
@ -424,7 +462,7 @@ impl Emitter for EmitterWriter {
|
||||||
let mut children = diag.children.clone();
|
let mut children = diag.children.clone();
|
||||||
let (mut primary_span, suggestions) = self.primary_span_formatted(&diag);
|
let (mut primary_span, suggestions) = self.primary_span_formatted(&diag);
|
||||||
|
|
||||||
self.fix_multispans_in_std_macros(
|
self.render_multispans_macro_backtrace_and_fix_extern_macros(
|
||||||
&self.sm,
|
&self.sm,
|
||||||
&mut primary_span,
|
&mut primary_span,
|
||||||
&mut children,
|
&mut children,
|
||||||
|
|
|
@ -945,14 +945,6 @@ impl SourceMap {
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
pub fn call_span_if_macro(&self, sp: Span) -> Span {
|
|
||||||
if self.span_to_filename(sp.clone()).is_macros() {
|
|
||||||
if let Some(use_site) = sp.macro_backtrace().last() {
|
|
||||||
return use_site.call_site;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sp
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue