Skip to content

Commit 217ca62

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 e4f9ddb commit 217ca62

File tree

1 file changed

+26
-21
lines changed

1 file changed

+26
-21
lines changed

src/libsyntax/ext/format.rs

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ enum Position {
3737

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

4246
/// Parsed argument expressions and the types that we've found so far for
@@ -307,7 +311,7 @@ impl<'a, 'b> Context<'a, 'b> {
307311
}
308312

309313
fn trans_count(&self, c: parse::Count) -> P<ast::Expr> {
310-
let sp = self.fmtsp;
314+
let sp = self.macsp;
311315
let count = |c, arg| {
312316
let mut path = Context::rtpath(self.ecx, "Count");
313317
path.push(self.ecx.ident_of(c));
@@ -345,7 +349,7 @@ impl<'a, 'b> Context<'a, 'b> {
345349
/// Translate a `parse::Piece` to a static `rt::Argument` or append
346350
/// to the `literal` string.
347351
fn trans_piece(&mut self, piece: &parse::Piece) -> Option<P<ast::Expr>> {
348-
let sp = self.fmtsp;
352+
let sp = self.macsp;
349353
match *piece {
350354
parse::String(s) => {
351355
self.literal.push_str(s);
@@ -441,22 +445,22 @@ impl<'a, 'b> Context<'a, 'b> {
441445
piece_ty: P<ast::Ty>,
442446
pieces: Vec<P<ast::Expr>>)
443447
-> P<ast::Expr> {
444-
let fmtsp = piece_ty.span;
445-
let ty = ecx.ty_rptr(fmtsp,
446-
ecx.ty(fmtsp, ast::TyVec(piece_ty)),
447-
Some(ecx.lifetime(fmtsp, special_idents::static_lifetime.name)),
448+
let sp = piece_ty.span;
449+
let ty = ecx.ty_rptr(sp,
450+
ecx.ty(sp, ast::TyVec(piece_ty)),
451+
Some(ecx.lifetime(sp, special_idents::static_lifetime.name)),
448452
ast::MutImmutable);
449-
let slice = ecx.expr_vec_slice(fmtsp, pieces);
453+
let slice = ecx.expr_vec_slice(sp, pieces);
450454
let st = ast::ItemStatic(ty, ast::MutImmutable, slice);
451455

452456
let name = ecx.ident_of(name);
453-
let item = ecx.item(fmtsp, name, vec![], st);
454-
let decl = respan(fmtsp, ast::DeclItem(item));
457+
let item = ecx.item(sp, name, vec![], st);
458+
let decl = respan(sp, ast::DeclItem(item));
455459

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

462466
/// Actually builds the expression which the iformat! block will be expanded
@@ -496,7 +500,7 @@ impl<'a, 'b> Context<'a, 'b> {
496500

497501
let name = self.ecx.ident_of(&format!("__arg{}", i));
498502
pats.push(self.ecx.pat_ident(e.span, name));
499-
locals.push(Context::format_arg(self.ecx, e.span, arg_ty,
503+
locals.push(Context::format_arg(self.ecx, self.macsp, e.span, arg_ty,
500504
self.ecx.expr_ident(e.span, name)));
501505
heads.push(self.ecx.expr_addr_of(e.span, e));
502506
}
@@ -514,7 +518,7 @@ impl<'a, 'b> Context<'a, 'b> {
514518
*name));
515519
pats.push(self.ecx.pat_ident(e.span, lname));
516520
names[*self.name_positions.get(name).unwrap()] =
517-
Some(Context::format_arg(self.ecx, e.span, arg_ty,
521+
Some(Context::format_arg(self.ecx, self.macsp, e.span, arg_ty,
518522
self.ecx.expr_ident(e.span, lname)));
519523
heads.push(self.ecx.expr_addr_of(e.span, e));
520524
}
@@ -565,7 +569,7 @@ impl<'a, 'b> Context<'a, 'b> {
565569
// Build up the static array which will store our precompiled
566570
// nonstandard placeholders, if there are any.
567571
let piece_ty = self.ecx.ty_path(self.ecx.path_global(
568-
self.fmtsp,
572+
self.macsp,
569573
Context::rtpath(self.ecx, "Argument")));
570574
let fmt = Context::static_array(self.ecx,
571575
"__STATIC_FMTARGS",
@@ -575,14 +579,14 @@ impl<'a, 'b> Context<'a, 'b> {
575579
("new_v1_formatted", vec![pieces, args_slice, fmt])
576580
};
577581

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

585-
fn format_arg(ecx: &ExtCtxt, sp: Span,
589+
fn format_arg(ecx: &ExtCtxt, macsp: Span, sp: Span,
586590
ty: &ArgumentType, arg: P<ast::Expr>)
587591
-> P<ast::Expr> {
588592
let trait_ = match *ty {
@@ -606,7 +610,7 @@ impl<'a, 'b> Context<'a, 'b> {
606610
}
607611
}
608612
Unsigned => {
609-
return ecx.expr_call_global(sp, vec![
613+
return ecx.expr_call_global(macsp, vec![
610614
ecx.ident_of_std("core"),
611615
ecx.ident_of("fmt"),
612616
ecx.ident_of("ArgumentV1"),
@@ -619,7 +623,7 @@ impl<'a, 'b> Context<'a, 'b> {
619623
ecx.ident_of("fmt"),
620624
ecx.ident_of(trait_),
621625
ecx.ident_of("fmt")]);
622-
ecx.expr_call_global(sp, vec![
626+
ecx.expr_call_global(macsp, vec![
623627
ecx.ident_of_std("core"),
624628
ecx.ident_of("fmt"),
625629
ecx.ident_of("ArgumentV1"),
@@ -649,6 +653,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span,
649653
names: HashMap<String, P<ast::Expr>>)
650654
-> P<ast::Expr> {
651655
let arg_types: Vec<_> = (0..args.len()).map(|_| None).collect();
656+
let macsp = ecx.call_site();
652657
let mut cx = Context {
653658
ecx: ecx,
654659
args: args,
@@ -663,9 +668,9 @@ 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+
macsp: macsp,
672+
fmtsp: efmt.span,
667673
};
668-
cx.fmtsp = efmt.span;
669674
let fmt = match expr_to_string(cx.ecx,
670675
efmt,
671676
"format argument must be a string literal.") {

0 commit comments

Comments
 (0)