Skip to content

Commit 0f46e4f

Browse files
committed
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
1 parent 6790b0e commit 0f46e4f

File tree

3 files changed

+12
-6
lines changed

3 files changed

+12
-6
lines changed

src/libsyntax/ext/expand.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
5555
fully_expanded.map(|e| ast::Expr {
5656
id: ast::DUMMY_NODE_ID,
5757
node: e.node,
58-
span: span,
58+
span: fld.new_span(span),
5959
})
6060
}
6161

src/libsyntax/ext/format.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use ext::base::*;
1717
use ext::base;
1818
use ext::build::AstBuilder;
1919
use fmt_macros as parse;
20+
use fold::Folder;
2021
use parse::token::special_idents;
2122
use parse::token;
2223
use ptr::P;
@@ -649,6 +650,10 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span,
649650
names: HashMap<String, P<ast::Expr>>)
650651
-> P<ast::Expr> {
651652
let arg_types: Vec<_> = (0..args.len()).map(|_| None).collect();
653+
// Expand the format literal so that efmt.span will have a backtrace. This
654+
// is essential for locating a bug when the format literal is generated in
655+
// a macro. (e.g. println!("{}"), which uses concat!($fmt, "\n")).
656+
let efmt = ecx.expander().fold_expr(efmt);
652657
let mut cx = Context {
653658
ecx: ecx,
654659
args: args,
@@ -663,9 +668,8 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span,
663668
pieces: Vec::new(),
664669
str_pieces: Vec::new(),
665670
all_pieces_simple: true,
666-
fmtsp: sp,
671+
fmtsp: efmt.span,
667672
};
668-
cx.fmtsp = efmt.span;
669673
let fmt = match expr_to_string(cx.ecx,
670674
efmt,
671675
"format argument must be a string literal.") {

src/libsyntax/fold.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1176,7 +1176,7 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span}: Expr, folder: &mut T) ->
11761176
}
11771177
ExprMethodCall(i, tps, args) => {
11781178
ExprMethodCall(
1179-
respan(i.span, folder.fold_ident(i.node)),
1179+
respan(folder.new_span(i.span), folder.fold_ident(i.node)),
11801180
tps.move_map(|x| folder.fold_ty(x)),
11811181
args.move_map(|x| folder.fold_expr(x)))
11821182
}
@@ -1246,11 +1246,13 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span}: Expr, folder: &mut T) ->
12461246
}
12471247
ExprField(el, ident) => {
12481248
ExprField(folder.fold_expr(el),
1249-
respan(ident.span, folder.fold_ident(ident.node)))
1249+
respan(folder.new_span(ident.span),
1250+
folder.fold_ident(ident.node)))
12501251
}
12511252
ExprTupField(el, ident) => {
12521253
ExprTupField(folder.fold_expr(el),
1253-
respan(ident.span, folder.fold_usize(ident.node)))
1254+
respan(folder.new_span(ident.span),
1255+
folder.fold_usize(ident.node)))
12541256
}
12551257
ExprIndex(el, er) => {
12561258
ExprIndex(folder.fold_expr(el), folder.fold_expr(er))

0 commit comments

Comments
 (0)