From b7bb67abd32ae15476cd40746cae7f9a96bc65da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 8 Dec 2017 18:35:55 -0800 Subject: [PATCH] Use spans for -Z external-macro-backtrace ``` % rustc ui/type-check/cannot_infer_local_or_vec.rs -Z external-macro-backtrace error[E0282]: type annotations needed --> :3:1 | 1 | / ( $ elem : expr ; $ n : expr ) => ( 2 | | $ crate :: vec :: from_elem ( $ elem , $ n ) ) ; ( $ ( $ x : expr ) , * ) => ( 3 | | < [ _ ] > :: into_vec ( box [ $ ( $ x ) , * ] ) ) ; ( $ ( $ x : expr , ) * ) | | ^^^^^^^^^^^^^^^^^^^^^ | | | | | cannot infer type for `T` 4 | | => ( vec ! [ $ ( $ x ) , * ] ) | |______________________________- in this expansion of `vec!` | ::: ui/type-check/cannot_infer_local_or_vec.rs | 12 | let x = vec![]; | - ------ in this macro invocation | | | consider giving `x` a type error: aborting due to previous error ``` --- src/librustc_errors/emitter.rs | 102 +++++++++--------- src/test/ui/macro_backtrace/auxiliary/ping.rs | 21 ++++ src/test/ui/macro_backtrace/main.rs | 5 +- src/test/ui/macro_backtrace/main.stderr | 86 +++++++++++++-- 4 files changed, 152 insertions(+), 62 deletions(-) diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 16bbd755b886..802563c7b6e5 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -64,11 +64,11 @@ fn emit(&mut self, db: &DiagnosticBuilder) { } } - if !db.handler.flags.external_macro_backtrace { - self.fix_multispans_in_std_macros(&mut primary_span, &mut children); - } + self.fix_multispans_in_std_macros(&mut primary_span, + &mut children, + db.handler.flags.external_macro_backtrace); + self.emit_messages_default(&db.level, - db.handler.flags.external_macro_backtrace, &db.styled_message(), &db.code, &primary_span, @@ -726,7 +726,9 @@ fn get_max_line_num(&mut self, span: &MultiSpan, children: &Vec) // 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_std_macros(&mut self, span: &mut MultiSpan) -> bool { + fn fix_multispan_in_std_macros(&mut self, + span: &mut MultiSpan, + always_backtrace: bool) -> bool { let mut spans_updated = false; if let Some(ref cm) = self.cm { @@ -739,22 +741,45 @@ fn fix_multispan_in_std_macros(&mut self, span: &mut MultiSpan) -> bool { continue; } let call_sp = cm.call_span_if_macro(*sp); - if call_sp != *sp { - before_after.push((sp.clone(), call_sp)); + if call_sp != *sp && !always_backtrace { + before_after.push((*sp, call_sp)); } - for trace in sp.macro_backtrace().iter().rev() { + let backtrace_len = sp.macro_backtrace().len(); + for (i, trace) in sp.macro_backtrace().iter().rev().enumerate() { // Only show macro locations that are local // and display them like a span_note if let Some(def_site) = trace.def_site_span { if def_site == DUMMY_SP { continue; } + if always_backtrace { + new_labels.push((def_site, + format!("in this expansion of `{}`{}", + trace.macro_decl_name, + if backtrace_len > 2 { + // if backtrace_len == 1 it'll be pointed + // at by "in this macro invocation" + format!(" (#{})", i + 1) + } else { + "".to_string() + }))); + } // Check to make sure we're not in any <*macros> if !cm.span_to_filename(def_site).contains("macros>") && - !trace.macro_decl_name.starts_with("#[") { + !trace.macro_decl_name.starts_with("#[") || + always_backtrace { new_labels.push((trace.call_site, - "in this macro invocation".to_string())); - break; + format!("in this macro invocation{}", + if backtrace_len > 2 && always_backtrace { + // only specify order when the macro + // backtrace is multiple levels deep + format!(" (#{})", i + 1) + } else { + "".to_string() + }))); + if !always_backtrace { + break; + } } } } @@ -766,7 +791,9 @@ fn fix_multispan_in_std_macros(&mut self, span: &mut MultiSpan) -> bool { if sp_label.span == DUMMY_SP { continue; } - if cm.span_to_filename(sp_label.span.clone()).contains("macros>") { + if cm.span_to_filename(sp_label.span.clone()).contains("macros>") && + !always_backtrace + { let v = sp_label.span.macro_backtrace(); if let Some(use_site) = v.last() { before_after.push((sp_label.span.clone(), use_site.call_site.clone())); @@ -788,18 +815,19 @@ fn fix_multispan_in_std_macros(&mut self, span: &mut MultiSpan) -> bool { // will change the span to point at the use site. fn fix_multispans_in_std_macros(&mut self, span: &mut MultiSpan, - children: &mut Vec) { - let mut spans_updated = self.fix_multispan_in_std_macros(span); + children: &mut Vec, + backtrace: bool) { + let mut spans_updated = self.fix_multispan_in_std_macros(span, backtrace); for child in children.iter_mut() { - spans_updated |= self.fix_multispan_in_std_macros(&mut child.span); + spans_updated |= self.fix_multispan_in_std_macros(&mut child.span, backtrace); } if spans_updated { children.push(SubDiagnostic { level: Level::Note, message: vec![ - (["this error originates in a macro outside of the current crate", - "(in Nightly builds, run with -Z external-macro-backtrace for more info)"] - .join(" "), + ("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(), Style::NoStyle), ], span: MultiSpan::new(), @@ -861,7 +889,7 @@ fn style_or_override(style: Style, override_style: Option