From 49d8b0dcbef738b70f08b6648bb7c358b491f47c Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Thu, 10 Sep 2015 21:22:59 +0200 Subject: [PATCH 1/4] Make print_macro_backtrace non-recursive --- src/libsyntax/diagnostic.rs | 48 ++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index 067e3fff3eb29..1924368a7f5fb 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -727,30 +727,34 @@ impl EmitterWriter { cm: &codemap::CodeMap, sp: Span) -> io::Result<()> { - let cs = try!(cm.with_expn_info(sp.expn_id, |expn_info| -> io::Result<_> { - match expn_info { - Some(ei) => { - let ss = ei.callee.span.map_or(String::new(), - |span| cm.span_to_string(span)); - let (pre, post) = match ei.callee.format { - codemap::MacroAttribute(..) => ("#[", "]"), - codemap::MacroBang(..) => ("", "!"), - codemap::CompilerExpansion(..) => ("", ""), - }; - try!(self.print_diagnostic(&ss, Note, - &format!("in expansion of {}{}{}", - pre, - ei.callee.name(), - post), - None)); - let ss = cm.span_to_string(ei.call_site); - try!(self.print_diagnostic(&ss, Note, "expansion site", None)); - Ok(Some(ei.call_site)) + let mut sp_opt = Some(sp); + while let Some(sp) = sp_opt { + sp_opt = try!(cm.with_expn_info(sp.expn_id, |expn_info| -> io::Result<_> { + match expn_info { + Some(ei) => { + let ss = ei.callee.span.map_or(String::new(), + |span| cm.span_to_string(span)); + let (pre, post) = match ei.callee.format { + codemap::MacroAttribute(..) => ("#[", "]"), + codemap::MacroBang(..) => ("", "!"), + codemap::CompilerExpansion(..) => ("", ""), + }; + try!(self.print_diagnostic(&ss, Note, + &format!("in expansion of {}{}{}", + pre, + ei.callee.name(), + post), + None)); + let ss = cm.span_to_string(ei.call_site); + try!(self.print_diagnostic(&ss, Note, "expansion site", None)); + Ok(Some(ei.call_site)) + } + None => Ok(None) } - None => Ok(None) + })); } - })); - cs.map_or(Ok(()), |call_site| self.print_macro_backtrace(cm, call_site)) + + Ok(()) } } From 31fa44b18e6e8bd42630d6495823ade6a5adaeba Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Thu, 10 Sep 2015 22:25:28 +0200 Subject: [PATCH 2/4] Don't print the macro definition site in backtraces This halves the backtrace length. The definition site wasn't very useful anyways, since it may be invalid (for compiler expansions) or located in another crate. Since the macro name is still printed, grepping for it is still an easy way of finding the definition. --- src/libsyntax/diagnostic.rs | 8 ++------ src/test/compile-fail/for-expn-2.rs | 2 +- .../macro-backtrace-invalid-internals.rs | 18 ++++++++++-------- .../compile-fail/macro-backtrace-nested.rs | 4 ++-- .../compile-fail/macro-backtrace-println.rs | 9 +++++---- .../compile-fail/method-macro-backtrace.rs | 2 +- 6 files changed, 21 insertions(+), 22 deletions(-) diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index 1924368a7f5fb..c383f26b4e33d 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -732,21 +732,17 @@ impl EmitterWriter { sp_opt = try!(cm.with_expn_info(sp.expn_id, |expn_info| -> io::Result<_> { match expn_info { Some(ei) => { - let ss = ei.callee.span.map_or(String::new(), - |span| cm.span_to_string(span)); let (pre, post) = match ei.callee.format { codemap::MacroAttribute(..) => ("#[", "]"), codemap::MacroBang(..) => ("", "!"), codemap::CompilerExpansion(..) => ("", ""), }; - try!(self.print_diagnostic(&ss, Note, - &format!("in expansion of {}{}{}", + try!(self.print_diagnostic(&cm.span_to_string(ei.call_site), Note, + &format!("in this expansion of {}{}{}", pre, ei.callee.name(), post), None)); - let ss = cm.span_to_string(ei.call_site); - try!(self.print_diagnostic(&ss, Note, "expansion site", None)); Ok(Some(ei.call_site)) } None => Ok(None) diff --git a/src/test/compile-fail/for-expn-2.rs b/src/test/compile-fail/for-expn-2.rs index 6b1dbf9d2d0ba..ce2315f3a38d4 100644 --- a/src/test/compile-fail/for-expn-2.rs +++ b/src/test/compile-fail/for-expn-2.rs @@ -10,7 +10,7 @@ // Test that we get an expansion stack for `for` loops. -// error-pattern:in expansion of for loop expansion +// error-pattern:in this expansion of for loop expansion fn main() { for t in &foo { diff --git a/src/test/compile-fail/macro-backtrace-invalid-internals.rs b/src/test/compile-fail/macro-backtrace-invalid-internals.rs index 34aa1c75872f3..5069ec7d2846a 100644 --- a/src/test/compile-fail/macro-backtrace-invalid-internals.rs +++ b/src/test/compile-fail/macro-backtrace-invalid-internals.rs @@ -10,25 +10,25 @@ // Macros in statement vs expression position handle backtraces differently. -macro_rules! fake_method_stmt { //~ NOTE in expansion of +macro_rules! fake_method_stmt { () => { 1.fake() //~ ERROR no method named `fake` found } } -macro_rules! fake_field_stmt { //~ NOTE in expansion of +macro_rules! fake_field_stmt { () => { 1.fake //~ ERROR no field with that name } } -macro_rules! fake_anon_field_stmt { //~ NOTE in expansion of +macro_rules! fake_anon_field_stmt { () => { (1).0 //~ ERROR type was not a tuple } } -macro_rules! fake_method_expr { //~ NOTE in expansion of +macro_rules! fake_method_expr { () => { 1.fake() //~ ERROR no method named `fake` found } @@ -47,11 +47,13 @@ macro_rules! fake_anon_field_expr { } fn main() { - fake_method_stmt!(); //~ NOTE expansion site - fake_field_stmt!(); //~ NOTE expansion site - fake_anon_field_stmt!(); //~ NOTE expansion site + fake_method_stmt!(); //~ NOTE in this expansion of + fake_field_stmt!(); //~ NOTE in this expansion of + fake_anon_field_stmt!(); //~ NOTE in this expansion of - let _ = fake_method_expr!(); //~ NOTE expansion site + let _ = fake_method_expr!(); //~ NOTE in this expansion of let _ = fake_field_expr!(); //~ ERROR no field with that name + //~^ NOTE in this expansion of let _ = fake_anon_field_expr!(); //~ ERROR type was not a tuple + //~^ NOTE in this expansion of } diff --git a/src/test/compile-fail/macro-backtrace-nested.rs b/src/test/compile-fail/macro-backtrace-nested.rs index 7c1dc1a468c76..a429681bb2181 100644 --- a/src/test/compile-fail/macro-backtrace-nested.rs +++ b/src/test/compile-fail/macro-backtrace-nested.rs @@ -19,11 +19,11 @@ macro_rules! call_nested_expr { () => (nested_expr!()) } -macro_rules! call_nested_expr_sum { //~ NOTE in expansion of +macro_rules! call_nested_expr_sum { () => { 1 + nested_expr!(); } //~ ERROR unresolved name } fn main() { 1 + call_nested_expr!(); //~ ERROR unresolved name - call_nested_expr_sum!(); //~ NOTE expansion site + call_nested_expr_sum!(); //~ NOTE in this expansion of } diff --git a/src/test/compile-fail/macro-backtrace-println.rs b/src/test/compile-fail/macro-backtrace-println.rs index 0c66bbfcf044a..294892662d464 100644 --- a/src/test/compile-fail/macro-backtrace-println.rs +++ b/src/test/compile-fail/macro-backtrace-println.rs @@ -16,14 +16,15 @@ fn print(_args: std::fmt::Arguments) {} -macro_rules! myprint { //~ NOTE in expansion of - ($($arg:tt)*) => (print(format_args!($($arg)*))); +macro_rules! myprint { + ($($arg:tt)*) => (print(format_args!($($arg)*))); //~ NOTE in this expansion of } -macro_rules! myprintln { //~ NOTE in expansion of +macro_rules! myprintln { ($fmt:expr) => (myprint!(concat!($fmt, "\n"))); //~ ERROR invalid reference to argument `0` + //~^ NOTE in this expansion of } fn main() { - myprintln!("{}"); //~ NOTE expansion site + myprintln!("{}"); //~ NOTE in this expansion of } diff --git a/src/test/compile-fail/method-macro-backtrace.rs b/src/test/compile-fail/method-macro-backtrace.rs index c9ef2df8e1326..967a8531b2c0a 100644 --- a/src/test/compile-fail/method-macro-backtrace.rs +++ b/src/test/compile-fail/method-macro-backtrace.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// forbid-output: in expansion of +// forbid-output: in this expansion of macro_rules! make_method { ($name:ident) => ( fn $name(&self) { } ) From f3308b9c9d9b0cd5ace3d1fa4d3b0194a78187d0 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Fri, 11 Sep 2015 11:48:44 +0200 Subject: [PATCH 3/4] Don't print duplicate macro backtrace frames --- src/libsyntax/diagnostic.rs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index c383f26b4e33d..c78086bda6432 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -727,7 +727,9 @@ impl EmitterWriter { cm: &codemap::CodeMap, sp: Span) -> io::Result<()> { + let mut last_span = codemap::DUMMY_SP; let mut sp_opt = Some(sp); + while let Some(sp) = sp_opt { sp_opt = try!(cm.with_expn_info(sp.expn_id, |expn_info| -> io::Result<_> { match expn_info { @@ -737,12 +739,16 @@ impl EmitterWriter { codemap::MacroBang(..) => ("", "!"), codemap::CompilerExpansion(..) => ("", ""), }; - try!(self.print_diagnostic(&cm.span_to_string(ei.call_site), Note, - &format!("in this expansion of {}{}{}", - pre, - ei.callee.name(), - post), - None)); + // Don't print recursive invocations + if ei.call_site != last_span { + last_span = ei.call_site; + try!(self.print_diagnostic(&cm.span_to_string(ei.call_site), Note, + &format!("in this expansion of {}{}{}", + pre, + ei.callee.name(), + post), + None)); + } Ok(Some(ei.call_site)) } None => Ok(None) From 0be755c24a81f3c7c07dcd50406c9f17bee0d6ac Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Mon, 14 Sep 2015 16:09:57 +0200 Subject: [PATCH 4/4] Print the file in which a macro was defined --- src/libsyntax/diagnostic.rs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index c78086bda6432..c177eb1f00bbd 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -742,11 +742,20 @@ impl EmitterWriter { // Don't print recursive invocations if ei.call_site != last_span { last_span = ei.call_site; - try!(self.print_diagnostic(&cm.span_to_string(ei.call_site), Note, - &format!("in this expansion of {}{}{}", - pre, - ei.callee.name(), - post), + + let mut diag_string = format!("in this expansion of {}{}{}", + pre, + ei.callee.name(), + post); + + if let Some(def_site_span) = ei.callee.span { + diag_string.push_str(&format!(" (defined in {})", + cm.span_to_filename(def_site_span))); + } + + try!(self.print_diagnostic(&cm.span_to_string(ei.call_site), + Note, + &diag_string, None)); } Ok(Some(ei.call_site))