Skip to content

Commit 8f286db

Browse files
committed
rustc_errors: split macro backtrace rendering from <*macros> hacks.
1 parent 442ae7f commit 8f286db

File tree

3 files changed

+97
-67
lines changed

3 files changed

+97
-67
lines changed

src/librustc_errors/annotate_snippet_emitter_writer.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ impl Emitter for AnnotateSnippetEmitterWriter {
3232
let mut children = diag.children.clone();
3333
let (mut primary_span, suggestions) = self.primary_span_formatted(&diag);
3434

35-
self.fix_multispans_in_std_macros(
35+
self.render_multispans_macro_backtrace_and_fix_extern_macros(
3636
&self.source_map,
3737
&mut primary_span,
3838
&mut children,

src/librustc_errors/emitter.rs

Lines changed: 96 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -280,72 +280,72 @@ pub trait Emitter {
280280
}
281281
}
282282

283-
// This does a small "fix" for multispans by looking to see if it can find any that
284-
// point directly at <*macros>. Since these are often difficult to read, this
285-
// will change the span to point at the use site.
286-
fn fix_multispans_in_std_macros(
283+
fn render_multispans_macro_backtrace_and_fix_extern_macros(
287284
&self,
288285
source_map: &Option<Lrc<SourceMap>>,
289286
span: &mut MultiSpan,
290287
children: &mut Vec<SubDiagnostic>,
291288
level: &Level,
292289
backtrace: bool,
293290
) {
294-
let mut spans_updated = self.fix_multispan_in_std_macros(source_map, span, backtrace);
295-
for child in children.iter_mut() {
296-
spans_updated |=
297-
self.fix_multispan_in_std_macros(source_map, &mut child.span, backtrace);
291+
self.render_multispans_macro_backtrace(source_map, span, children, backtrace);
292+
293+
if !backtrace {
294+
if self.fix_multispans_in_extern_macros(source_map, span, children) {
295+
let msg = if level == &Error {
296+
"this error originates in a macro outside of the current crate \
297+
(in Nightly builds, run with -Z external-macro-backtrace \
298+
for more info)"
299+
.to_string()
300+
} else {
301+
"this warning originates in a macro outside of the current crate \
302+
(in Nightly builds, run with -Z external-macro-backtrace \
303+
for more info)"
304+
.to_string()
305+
};
306+
307+
children.push(SubDiagnostic {
308+
level: Level::Note,
309+
message: vec![(msg, Style::NoStyle)],
310+
span: MultiSpan::new(),
311+
render_span: None,
312+
});
313+
}
298314
}
299-
let msg = if level == &Error {
300-
"this error originates in a macro outside of the current crate \
301-
(in Nightly builds, run with -Z external-macro-backtrace \
302-
for more info)"
303-
.to_string()
304-
} else {
305-
"this warning originates in a macro outside of the current crate \
306-
(in Nightly builds, run with -Z external-macro-backtrace \
307-
for more info)"
308-
.to_string()
309-
};
315+
}
310316

311-
if spans_updated {
312-
children.push(SubDiagnostic {
313-
level: Level::Note,
314-
message: vec![(msg, Style::NoStyle)],
315-
span: MultiSpan::new(),
316-
render_span: None,
317-
});
317+
fn render_multispans_macro_backtrace(
318+
&self,
319+
source_map: &Option<Lrc<SourceMap>>,
320+
span: &mut MultiSpan,
321+
children: &mut Vec<SubDiagnostic>,
322+
backtrace: bool,
323+
) {
324+
self.render_multispan_macro_backtrace(source_map, span, backtrace);
325+
for child in children.iter_mut() {
326+
self.render_multispan_macro_backtrace(source_map, &mut child.span, backtrace);
318327
}
319328
}
320329

321-
// This "fixes" MultiSpans that contain Spans that are pointing to locations inside of
322-
// <*macros>. Since these locations are often difficult to read, we move these Spans from
323-
// <*macros> to their corresponding use site.
324-
fn fix_multispan_in_std_macros(
330+
fn render_multispan_macro_backtrace(
325331
&self,
326332
source_map: &Option<Lrc<SourceMap>>,
327333
span: &mut MultiSpan,
328334
always_backtrace: bool,
329-
) -> bool {
335+
) {
330336
let sm = match source_map {
331337
Some(ref sm) => sm,
332-
None => return false,
338+
None => return,
333339
};
334340

335-
let mut before_after: Vec<(Span, Span)> = vec![];
336341
let mut new_labels: Vec<(Span, String)> = vec![];
337342

338343
// First, find all the spans in <*macros> and point instead at their use site
339-
for sp in span.primary_spans() {
344+
for &sp in span.primary_spans() {
340345
if sp.is_dummy() {
341346
continue;
342347
}
343-
let call_sp = sm.call_span_if_macro(*sp);
344-
if call_sp != *sp && !always_backtrace {
345-
before_after.push((*sp, call_sp));
346-
}
347348
let macro_backtrace: Vec<_> = sp.macro_backtrace().collect();
348-
let backtrace_len = macro_backtrace.len();
349349
for (i, trace) in macro_backtrace.iter().rev().enumerate() {
350350
// Only show macro locations that are local
351351
// and display them like a span_note
@@ -358,13 +358,13 @@ pub trait Emitter {
358358
format!(
359359
"in this expansion of `{}`{}",
360360
trace.kind.descr(),
361-
if backtrace_len > 2 {
362-
// if backtrace_len == 1 it'll be pointed
363-
// at by "in this macro invocation"
361+
if macro_backtrace.len() > 2 {
362+
// if macro_backtrace.len() == 1 it'll be
363+
// pointed at by "in this macro invocation"
364364
format!(" (#{})", i + 1)
365365
} else {
366366
String::new()
367-
}
367+
},
368368
),
369369
));
370370
}
@@ -377,13 +377,13 @@ pub trait Emitter {
377377
trace.call_site,
378378
format!(
379379
"in this macro invocation{}",
380-
if backtrace_len > 2 && always_backtrace {
380+
if macro_backtrace.len() > 2 && always_backtrace {
381381
// only specify order when the macro
382382
// backtrace is multiple levels deep
383383
format!(" (#{})", i + 1)
384384
} else {
385385
String::new()
386-
}
386+
},
387387
),
388388
));
389389
if !always_backtrace {
@@ -395,20 +395,58 @@ pub trait Emitter {
395395
for (label_span, label_text) in new_labels {
396396
span.push_span_label(label_span, label_text);
397397
}
398-
for sp_label in span.span_labels() {
399-
if sp_label.span.is_dummy() {
400-
continue;
401-
}
402-
if sm.span_to_filename(sp_label.span.clone()).is_macros() && !always_backtrace {
403-
if let Some(use_site) = sp_label.span.macro_backtrace().last() {
404-
before_after.push((sp_label.span, use_site.call_site));
405-
}
406-
}
398+
}
399+
400+
// This does a small "fix" for multispans by looking to see if it can find any that
401+
// point directly at <*macros>. Since these are often difficult to read, this
402+
// will change the span to point at the use site.
403+
fn fix_multispans_in_extern_macros(
404+
&self,
405+
source_map: &Option<Lrc<SourceMap>>,
406+
span: &mut MultiSpan,
407+
children: &mut Vec<SubDiagnostic>,
408+
) -> bool {
409+
let mut spans_updated = self.fix_multispan_in_extern_macros(source_map, span);
410+
for child in children.iter_mut() {
411+
spans_updated |= self.fix_multispan_in_extern_macros(source_map, &mut child.span);
407412
}
413+
spans_updated
414+
}
415+
416+
// This "fixes" MultiSpans that contain Spans that are pointing to locations inside of
417+
// <*macros>. Since these locations are often difficult to read, we move these Spans from
418+
// <*macros> to their corresponding use site.
419+
fn fix_multispan_in_extern_macros(
420+
&self,
421+
source_map: &Option<Lrc<SourceMap>>,
422+
span: &mut MultiSpan,
423+
) -> bool {
424+
let sm = match source_map {
425+
Some(ref sm) => sm,
426+
None => return false,
427+
};
428+
429+
// First, find all the spans in <*macros> and point instead at their use site
430+
let replacements: Vec<(Span, Span)> = span
431+
.primary_spans()
432+
.iter()
433+
.copied()
434+
.chain(span.span_labels().iter().map(|sp_label| sp_label.span))
435+
.filter_map(|sp| {
436+
if !sp.is_dummy() && sm.span_to_filename(sp).is_macros() {
437+
let maybe_callsite = sp.source_callsite();
438+
if sp != maybe_callsite {
439+
return Some((sp, maybe_callsite));
440+
}
441+
}
442+
None
443+
})
444+
.collect();
445+
408446
// After we have them, make sure we replace these 'bad' def sites with their use sites
409-
let spans_updated = !before_after.is_empty();
410-
for (before, after) in before_after {
411-
span.replace(before, after);
447+
let spans_updated = !replacements.is_empty();
448+
for (from, to) in replacements {
449+
span.replace(from, to);
412450
}
413451

414452
spans_updated
@@ -424,7 +462,7 @@ impl Emitter for EmitterWriter {
424462
let mut children = diag.children.clone();
425463
let (mut primary_span, suggestions) = self.primary_span_formatted(&diag);
426464

427-
self.fix_multispans_in_std_macros(
465+
self.render_multispans_macro_backtrace_and_fix_extern_macros(
428466
&self.sm,
429467
&mut primary_span,
430468
&mut children,

src/librustc_span/source_map.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -945,14 +945,6 @@ impl SourceMap {
945945
_ => None,
946946
})
947947
}
948-
pub fn call_span_if_macro(&self, sp: Span) -> Span {
949-
if self.span_to_filename(sp.clone()).is_macros() {
950-
if let Some(use_site) = sp.macro_backtrace().last() {
951-
return use_site.call_site;
952-
}
953-
}
954-
sp
955-
}
956948
}
957949

958950
#[derive(Clone)]

0 commit comments

Comments
 (0)