Skip to content

Commit bd26307

Browse files
committed
Use the ecx.call_site() span for generating refs to format_args! internals
`format_args!` uses `#[allow_internal_unstable]` to access internal functions and structs that are marked unstable. For this to work, the spans on AST nodes referencing unstable internals must be equal (same lo/hi values) to the `format_args!` call site, so that the stability checker can recognize that the AST node was generated by the macro.
1 parent 47def3e commit bd26307

File tree

1 file changed

+25
-19
lines changed

1 file changed

+25
-19
lines changed

src/libsyntax/ext/format.rs

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ enum Position {
3838

3939
struct Context<'a, 'b:'a> {
4040
ecx: &'a mut ExtCtxt<'b>,
41+
/// The macro's call site. References to unstable formatting internals must
42+
/// use this span to pass the stability checker.
43+
macsp: Span,
44+
/// The span of the format string literal.
4145
fmtsp: Span,
4246

4347
/// Parsed argument expressions and the types that we've found so far for
@@ -308,7 +312,7 @@ impl<'a, 'b> Context<'a, 'b> {
308312
}
309313

310314
fn trans_count(&self, c: parse::Count) -> P<ast::Expr> {
311-
let sp = self.fmtsp;
315+
let sp = self.macsp;
312316
let count = |c, arg| {
313317
let mut path = Context::rtpath(self.ecx, "Count");
314318
path.push(self.ecx.ident_of(c));
@@ -346,7 +350,7 @@ impl<'a, 'b> Context<'a, 'b> {
346350
/// Translate a `parse::Piece` to a static `rt::Argument` or append
347351
/// to the `literal` string.
348352
fn trans_piece(&mut self, piece: &parse::Piece) -> Option<P<ast::Expr>> {
349-
let sp = self.fmtsp;
353+
let sp = self.macsp;
350354
match *piece {
351355
parse::String(s) => {
352356
self.literal.push_str(s);
@@ -442,22 +446,22 @@ impl<'a, 'b> Context<'a, 'b> {
442446
piece_ty: P<ast::Ty>,
443447
pieces: Vec<P<ast::Expr>>)
444448
-> P<ast::Expr> {
445-
let fmtsp = piece_ty.span;
446-
let ty = ecx.ty_rptr(fmtsp,
447-
ecx.ty(fmtsp, ast::TyVec(piece_ty)),
448-
Some(ecx.lifetime(fmtsp, special_idents::static_lifetime.name)),
449+
let sp = piece_ty.span;
450+
let ty = ecx.ty_rptr(sp,
451+
ecx.ty(sp, ast::TyVec(piece_ty)),
452+
Some(ecx.lifetime(sp, special_idents::static_lifetime.name)),
449453
ast::MutImmutable);
450-
let slice = ecx.expr_vec_slice(fmtsp, pieces);
454+
let slice = ecx.expr_vec_slice(sp, pieces);
451455
let st = ast::ItemStatic(ty, ast::MutImmutable, slice);
452456

453457
let name = ecx.ident_of(name);
454-
let item = ecx.item(fmtsp, name, vec![], st);
455-
let decl = respan(fmtsp, ast::DeclItem(item));
458+
let item = ecx.item(sp, name, vec![], st);
459+
let decl = respan(sp, ast::DeclItem(item));
456460

457461
// Wrap the declaration in a block so that it forms a single expression.
458-
ecx.expr_block(ecx.block(fmtsp,
459-
vec![P(respan(fmtsp, ast::StmtDecl(P(decl), ast::DUMMY_NODE_ID)))],
460-
Some(ecx.expr_ident(fmtsp, name))))
462+
ecx.expr_block(ecx.block(sp,
463+
vec![P(respan(sp, ast::StmtDecl(P(decl), ast::DUMMY_NODE_ID)))],
464+
Some(ecx.expr_ident(sp, name))))
461465
}
462466

463467
/// Actually builds the expression which the iformat! block will be expanded
@@ -497,7 +501,7 @@ impl<'a, 'b> Context<'a, 'b> {
497501

498502
let name = self.ecx.ident_of(&format!("__arg{}", i));
499503
pats.push(self.ecx.pat_ident(e.span, name));
500-
locals.push(Context::format_arg(self.ecx, e.span, arg_ty,
504+
locals.push(Context::format_arg(self.ecx, self.macsp, e.span, arg_ty,
501505
self.ecx.expr_ident(e.span, name)));
502506
heads.push(self.ecx.expr_addr_of(e.span, e));
503507
}
@@ -515,7 +519,7 @@ impl<'a, 'b> Context<'a, 'b> {
515519
*name));
516520
pats.push(self.ecx.pat_ident(e.span, lname));
517521
names[*self.name_positions.get(name).unwrap()] =
518-
Some(Context::format_arg(self.ecx, e.span, arg_ty,
522+
Some(Context::format_arg(self.ecx, self.macsp, e.span, arg_ty,
519523
self.ecx.expr_ident(e.span, lname)));
520524
heads.push(self.ecx.expr_addr_of(e.span, e));
521525
}
@@ -566,7 +570,7 @@ impl<'a, 'b> Context<'a, 'b> {
566570
// Build up the static array which will store our precompiled
567571
// nonstandard placeholders, if there are any.
568572
let piece_ty = self.ecx.ty_path(self.ecx.path_global(
569-
self.fmtsp,
573+
self.macsp,
570574
Context::rtpath(self.ecx, "Argument")));
571575
let fmt = Context::static_array(self.ecx,
572576
"__STATIC_FMTARGS",
@@ -576,14 +580,14 @@ impl<'a, 'b> Context<'a, 'b> {
576580
("new_v1_formatted", vec![pieces, args_slice, fmt])
577581
};
578582

579-
self.ecx.expr_call_global(self.fmtsp, vec!(
583+
self.ecx.expr_call_global(self.macsp, vec!(
580584
self.ecx.ident_of_std("core"),
581585
self.ecx.ident_of("fmt"),
582586
self.ecx.ident_of("Arguments"),
583587
self.ecx.ident_of(fn_name)), fn_args)
584588
}
585589

586-
fn format_arg(ecx: &ExtCtxt, sp: Span,
590+
fn format_arg(ecx: &ExtCtxt, macsp: Span, sp: Span,
587591
ty: &ArgumentType, arg: P<ast::Expr>)
588592
-> P<ast::Expr> {
589593
let trait_ = match *ty {
@@ -607,7 +611,7 @@ impl<'a, 'b> Context<'a, 'b> {
607611
}
608612
}
609613
Unsigned => {
610-
return ecx.expr_call_global(sp, vec![
614+
return ecx.expr_call_global(macsp, vec![
611615
ecx.ident_of_std("core"),
612616
ecx.ident_of("fmt"),
613617
ecx.ident_of("ArgumentV1"),
@@ -620,7 +624,7 @@ impl<'a, 'b> Context<'a, 'b> {
620624
ecx.ident_of("fmt"),
621625
ecx.ident_of(trait_),
622626
ecx.ident_of("fmt")]);
623-
ecx.expr_call_global(sp, vec![
627+
ecx.expr_call_global(macsp, vec![
624628
ecx.ident_of_std("core"),
625629
ecx.ident_of("fmt"),
626630
ecx.ident_of("ArgumentV1"),
@@ -650,6 +654,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span,
650654
names: HashMap<String, P<ast::Expr>>)
651655
-> P<ast::Expr> {
652656
let arg_types: Vec<_> = (0..args.len()).map(|_| None).collect();
657+
let macsp = ecx.call_site();
653658
// Expand the format literal so that efmt.span will have a backtrace. This
654659
// is essential for locating a bug when the format literal is generated in
655660
// a macro. (e.g. println!("{}"), which uses concat!($fmt, "\n")).
@@ -668,6 +673,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span,
668673
pieces: Vec::new(),
669674
str_pieces: Vec::new(),
670675
all_pieces_simple: true,
676+
macsp: macsp,
671677
fmtsp: efmt.span,
672678
};
673679
let fmt = match expr_to_string(cx.ecx,

0 commit comments

Comments
 (0)