Skip to content

Commit 159d249

Browse files
committed
annotate-snippet emitter: Deal with multispans from macros, too
This moves the two methods from the `EmitterWriter` impl to trait default methods in the `Emitter` trait so that they can be re-used by the `AnnotateSnippetEmitterWriter`. Closes #61810
1 parent f257c40 commit 159d249

File tree

2 files changed

+137
-126
lines changed

2 files changed

+137
-126
lines changed

src/librustc_errors/annotate_snippet_emitter_writer.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,14 @@ pub struct AnnotateSnippetEmitterWriter {
3030
impl Emitter for AnnotateSnippetEmitterWriter {
3131
/// The entry point for the diagnostics generation
3232
fn emit_diagnostic(&mut self, db: &DiagnosticBuilder<'_>) {
33-
let children = db.children.clone();
34-
let (primary_span, suggestions) = self.primary_span_formatted(&db);
35-
36-
// FIXME(#59346): Add `fix_multispans_in_std_macros` function from emitter.rs
33+
let mut children = db.children.clone();
34+
let (mut primary_span, suggestions) = self.primary_span_formatted(&db);
35+
36+
self.fix_multispans_in_std_macros(&self.source_map,
37+
&mut primary_span,
38+
&mut children,
39+
&db.level,
40+
db.handler.flags.external_macro_backtrace);
3741

3842
self.emit_messages_default(&db.level,
3943
db.message(),

src/librustc_errors/emitter.rs

+129-122
Original file line numberDiff line numberDiff line change
@@ -247,14 +247,142 @@ pub trait Emitter {
247247
(primary_span, &db.suggestions)
248248
}
249249
}
250+
251+
// This does a small "fix" for multispans by looking to see if it can find any that
252+
// point directly at <*macros>. Since these are often difficult to read, this
253+
// will change the span to point at the use site.
254+
fn fix_multispans_in_std_macros(&self,
255+
source_map: &Option<Lrc<SourceMapperDyn>>,
256+
span: &mut MultiSpan,
257+
children: &mut Vec<SubDiagnostic>,
258+
level: &Level,
259+
backtrace: bool) {
260+
let mut spans_updated = self.fix_multispan_in_std_macros(source_map, span, backtrace);
261+
for child in children.iter_mut() {
262+
spans_updated |= self.fix_multispan_in_std_macros(
263+
source_map,
264+
&mut child.span,
265+
backtrace
266+
);
267+
}
268+
let msg = if level == &Error {
269+
"this error originates in a macro outside of the current crate \
270+
(in Nightly builds, run with -Z external-macro-backtrace \
271+
for more info)".to_string()
272+
} else {
273+
"this warning originates in a macro outside of the current crate \
274+
(in Nightly builds, run with -Z external-macro-backtrace \
275+
for more info)".to_string()
276+
};
277+
278+
if spans_updated {
279+
children.push(SubDiagnostic {
280+
level: Level::Note,
281+
message: vec![
282+
(msg,
283+
Style::NoStyle),
284+
],
285+
span: MultiSpan::new(),
286+
render_span: None,
287+
});
288+
}
289+
}
290+
291+
// This "fixes" MultiSpans that contain Spans that are pointing to locations inside of
292+
// <*macros>. Since these locations are often difficult to read, we move these Spans from
293+
// <*macros> to their corresponding use site.
294+
fn fix_multispan_in_std_macros(&self,
295+
source_map: &Option<Lrc<SourceMapperDyn>>,
296+
span: &mut MultiSpan,
297+
always_backtrace: bool) -> bool {
298+
let mut spans_updated = false;
299+
300+
if let Some(ref sm) = source_map {
301+
let mut before_after: Vec<(Span, Span)> = vec![];
302+
let mut new_labels: Vec<(Span, String)> = vec![];
303+
304+
// First, find all the spans in <*macros> and point instead at their use site
305+
for sp in span.primary_spans() {
306+
if sp.is_dummy() {
307+
continue;
308+
}
309+
let call_sp = sm.call_span_if_macro(*sp);
310+
if call_sp != *sp && !always_backtrace {
311+
before_after.push((*sp, call_sp));
312+
}
313+
let backtrace_len = sp.macro_backtrace().len();
314+
for (i, trace) in sp.macro_backtrace().iter().rev().enumerate() {
315+
// Only show macro locations that are local
316+
// and display them like a span_note
317+
if trace.def_site_span.is_dummy() {
318+
continue;
319+
}
320+
if always_backtrace {
321+
new_labels.push((trace.def_site_span,
322+
format!("in this expansion of `{}`{}",
323+
trace.macro_decl_name,
324+
if backtrace_len > 2 {
325+
// if backtrace_len == 1 it'll be pointed
326+
// at by "in this macro invocation"
327+
format!(" (#{})", i + 1)
328+
} else {
329+
String::new()
330+
})));
331+
}
332+
// Check to make sure we're not in any <*macros>
333+
if !sm.span_to_filename(trace.def_site_span).is_macros() &&
334+
!trace.macro_decl_name.starts_with("desugaring of ") &&
335+
!trace.macro_decl_name.starts_with("#[") ||
336+
always_backtrace {
337+
new_labels.push((trace.call_site,
338+
format!("in this macro invocation{}",
339+
if backtrace_len > 2 && always_backtrace {
340+
// only specify order when the macro
341+
// backtrace is multiple levels deep
342+
format!(" (#{})", i + 1)
343+
} else {
344+
String::new()
345+
})));
346+
if !always_backtrace {
347+
break;
348+
}
349+
}
350+
}
351+
}
352+
for (label_span, label_text) in new_labels {
353+
span.push_span_label(label_span, label_text);
354+
}
355+
for sp_label in span.span_labels() {
356+
if sp_label.span.is_dummy() {
357+
continue;
358+
}
359+
if sm.span_to_filename(sp_label.span.clone()).is_macros() &&
360+
!always_backtrace
361+
{
362+
let v = sp_label.span.macro_backtrace();
363+
if let Some(use_site) = v.last() {
364+
before_after.push((sp_label.span.clone(), use_site.call_site.clone()));
365+
}
366+
}
367+
}
368+
// After we have them, make sure we replace these 'bad' def sites with their use sites
369+
for (before, after) in before_after {
370+
span.replace(before, after);
371+
spans_updated = true;
372+
}
373+
}
374+
375+
spans_updated
376+
}
250377
}
251378

252379
impl Emitter for EmitterWriter {
253380
fn emit_diagnostic(&mut self, db: &DiagnosticBuilder<'_>) {
254381
let mut children = db.children.clone();
255382
let (mut primary_span, suggestions) = self.primary_span_formatted(&db);
256383

257-
self.fix_multispans_in_std_macros(&mut primary_span,
384+
self.fix_multispans_in_std_macros(&self.sm,
385+
&mut primary_span,
258386
&mut children,
259387
&db.level,
260388
db.handler.flags.external_macro_backtrace);
@@ -919,127 +1047,6 @@ impl EmitterWriter {
9191047
max
9201048
}
9211049

922-
// This "fixes" MultiSpans that contain Spans that are pointing to locations inside of
923-
// <*macros>. Since these locations are often difficult to read, we move these Spans from
924-
// <*macros> to their corresponding use site.
925-
fn fix_multispan_in_std_macros(&mut self,
926-
span: &mut MultiSpan,
927-
always_backtrace: bool) -> bool {
928-
let mut spans_updated = false;
929-
930-
if let Some(ref sm) = self.sm {
931-
let mut before_after: Vec<(Span, Span)> = vec![];
932-
let mut new_labels: Vec<(Span, String)> = vec![];
933-
934-
// First, find all the spans in <*macros> and point instead at their use site
935-
for sp in span.primary_spans() {
936-
if sp.is_dummy() {
937-
continue;
938-
}
939-
let call_sp = sm.call_span_if_macro(*sp);
940-
if call_sp != *sp && !always_backtrace {
941-
before_after.push((*sp, call_sp));
942-
}
943-
let backtrace_len = sp.macro_backtrace().len();
944-
for (i, trace) in sp.macro_backtrace().iter().rev().enumerate() {
945-
// Only show macro locations that are local
946-
// and display them like a span_note
947-
if trace.def_site_span.is_dummy() {
948-
continue;
949-
}
950-
if always_backtrace {
951-
new_labels.push((trace.def_site_span,
952-
format!("in this expansion of `{}`{}",
953-
trace.macro_decl_name,
954-
if backtrace_len > 2 {
955-
// if backtrace_len == 1 it'll be pointed
956-
// at by "in this macro invocation"
957-
format!(" (#{})", i + 1)
958-
} else {
959-
String::new()
960-
})));
961-
}
962-
// Check to make sure we're not in any <*macros>
963-
if !sm.span_to_filename(trace.def_site_span).is_macros() &&
964-
!trace.macro_decl_name.starts_with("desugaring of ") &&
965-
!trace.macro_decl_name.starts_with("#[") ||
966-
always_backtrace {
967-
new_labels.push((trace.call_site,
968-
format!("in this macro invocation{}",
969-
if backtrace_len > 2 && always_backtrace {
970-
// only specify order when the macro
971-
// backtrace is multiple levels deep
972-
format!(" (#{})", i + 1)
973-
} else {
974-
String::new()
975-
})));
976-
if !always_backtrace {
977-
break;
978-
}
979-
}
980-
}
981-
}
982-
for (label_span, label_text) in new_labels {
983-
span.push_span_label(label_span, label_text);
984-
}
985-
for sp_label in span.span_labels() {
986-
if sp_label.span.is_dummy() {
987-
continue;
988-
}
989-
if sm.span_to_filename(sp_label.span.clone()).is_macros() &&
990-
!always_backtrace
991-
{
992-
let v = sp_label.span.macro_backtrace();
993-
if let Some(use_site) = v.last() {
994-
before_after.push((sp_label.span.clone(), use_site.call_site.clone()));
995-
}
996-
}
997-
}
998-
// After we have them, make sure we replace these 'bad' def sites with their use sites
999-
for (before, after) in before_after {
1000-
span.replace(before, after);
1001-
spans_updated = true;
1002-
}
1003-
}
1004-
1005-
spans_updated
1006-
}
1007-
1008-
// This does a small "fix" for multispans by looking to see if it can find any that
1009-
// point directly at <*macros>. Since these are often difficult to read, this
1010-
// will change the span to point at the use site.
1011-
fn fix_multispans_in_std_macros(&mut self,
1012-
span: &mut MultiSpan,
1013-
children: &mut Vec<SubDiagnostic>,
1014-
level: &Level,
1015-
backtrace: bool) {
1016-
let mut spans_updated = self.fix_multispan_in_std_macros(span, backtrace);
1017-
for child in children.iter_mut() {
1018-
spans_updated |= self.fix_multispan_in_std_macros(&mut child.span, backtrace);
1019-
}
1020-
let msg = if level == &Error {
1021-
"this error originates in a macro outside of the current crate \
1022-
(in Nightly builds, run with -Z external-macro-backtrace \
1023-
for more info)".to_string()
1024-
} else {
1025-
"this warning originates in a macro outside of the current crate \
1026-
(in Nightly builds, run with -Z external-macro-backtrace \
1027-
for more info)".to_string()
1028-
};
1029-
1030-
if spans_updated {
1031-
children.push(SubDiagnostic {
1032-
level: Level::Note,
1033-
message: vec![
1034-
(msg,
1035-
Style::NoStyle),
1036-
],
1037-
span: MultiSpan::new(),
1038-
render_span: None,
1039-
});
1040-
}
1041-
}
1042-
10431050
/// Adds a left margin to every line but the first, given a padding length and the label being
10441051
/// displayed, keeping the provided highlighting.
10451052
fn msg_to_buffer(&self,

0 commit comments

Comments
 (0)