diff options
| author | Ryan Prichard <ryan.prichard@gmail.com> | 2015-04-03 01:27:04 -0700 |
|---|---|---|
| committer | Ryan Prichard <ryan.prichard@gmail.com> | 2015-04-11 16:00:58 -0700 |
| commit | 0f46e4f1f23368f4615a9847671e3a91b2ebaf18 (patch) | |
| tree | 23795acb7872118fdbcce722b0448004d06be9cd /src/libsyntax/ext | |
| parent | 6790b0e51967b1487728d155e0800a1ed03a30d3 (diff) | |
| download | rust-0f46e4f1f23368f4615a9847671e3a91b2ebaf18.tar.gz rust-0f46e4f1f23368f4615a9847671e3a91b2ebaf18.zip | |
Propagate macro backtraces more often, improve formatting diagnostics
* In noop_fold_expr, call new_span in these cases:
- ExprMethodCall's identifier
- ExprField's identifier
- ExprTupField's integer
Calling new_span for ExprMethodCall's identifier is necessary to print
an acceptable diagnostic for write!(&2, ""). We see this error:
<std macros>:2:20: 2:66 error: type `&mut _` does not implement any method in scope named `write_fmt`
<std macros>:2 ( & mut * $ dst ) . write_fmt ( format_args ! ( $ ( $ arg ) * ) ) )
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
With this change, we also see a macro expansion backtrace leading to
the write!(&2, "") call site.
* After fully expanding a macro, we replace the expansion expression's
span with the original span. Call fld.new_span to add a backtrace to
this span. (Note that I'm call new_span after bt.pop(), so the macro
just expanded isn't on the backtrace.)
The motivating example for this change is println!("{}"). The format
string literal is concat!($fmt, "arg") and is inside the libstd macro.
We need to see the backtrace to find the println! call site.
* Add a backtrace to the format_args! format expression span.
Addresses #23459
Diffstat (limited to 'src/libsyntax/ext')
| -rw-r--r-- | src/libsyntax/ext/expand.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/ext/format.rs | 8 |
2 files changed, 7 insertions, 3 deletions
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 5f4ec01791c..b65798b8a49 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -55,7 +55,7 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> { fully_expanded.map(|e| ast::Expr { id: ast::DUMMY_NODE_ID, node: e.node, - span: span, + span: fld.new_span(span), }) } diff --git a/src/libsyntax/ext/format.rs b/src/libsyntax/ext/format.rs index 1d99a475b32..513bbf6c77b 100644 --- a/src/libsyntax/ext/format.rs +++ b/src/libsyntax/ext/format.rs @@ -17,6 +17,7 @@ use ext::base::*; use ext::base; use ext::build::AstBuilder; use fmt_macros as parse; +use fold::Folder; use parse::token::special_idents; use parse::token; use ptr::P; @@ -649,6 +650,10 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span, names: HashMap<String, P<ast::Expr>>) -> P<ast::Expr> { let arg_types: Vec<_> = (0..args.len()).map(|_| None).collect(); + // Expand the format literal so that efmt.span will have a backtrace. This + // is essential for locating a bug when the format literal is generated in + // a macro. (e.g. println!("{}"), which uses concat!($fmt, "\n")). + let efmt = ecx.expander().fold_expr(efmt); let mut cx = Context { ecx: ecx, args: args, @@ -663,9 +668,8 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span, pieces: Vec::new(), str_pieces: Vec::new(), all_pieces_simple: true, - fmtsp: sp, + fmtsp: efmt.span, }; - cx.fmtsp = efmt.span; let fmt = match expr_to_string(cx.ecx, efmt, "format argument must be a string literal.") { |
