@@ -38,6 +38,10 @@ enum Position {
38
38
39
39
struct Context < ' a , ' b : ' a > {
40
40
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.
41
45
fmtsp : Span ,
42
46
43
47
/// Parsed argument expressions and the types that we've found so far for
@@ -308,7 +312,7 @@ impl<'a, 'b> Context<'a, 'b> {
308
312
}
309
313
310
314
fn trans_count ( & self , c : parse:: Count ) -> P < ast:: Expr > {
311
- let sp = self . fmtsp ;
315
+ let sp = self . macsp ;
312
316
let count = |c, arg| {
313
317
let mut path = Context :: rtpath ( self . ecx , "Count" ) ;
314
318
path. push ( self . ecx . ident_of ( c) ) ;
@@ -346,7 +350,7 @@ impl<'a, 'b> Context<'a, 'b> {
346
350
/// Translate a `parse::Piece` to a static `rt::Argument` or append
347
351
/// to the `literal` string.
348
352
fn trans_piece ( & mut self , piece : & parse:: Piece ) -> Option < P < ast:: Expr > > {
349
- let sp = self . fmtsp ;
353
+ let sp = self . macsp ;
350
354
match * piece {
351
355
parse:: String ( s) => {
352
356
self . literal . push_str ( s) ;
@@ -442,22 +446,22 @@ impl<'a, 'b> Context<'a, 'b> {
442
446
piece_ty : P < ast:: Ty > ,
443
447
pieces : Vec < P < ast:: Expr > > )
444
448
-> 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 ) ) ,
449
453
ast:: MutImmutable ) ;
450
- let slice = ecx. expr_vec_slice ( fmtsp , pieces) ;
454
+ let slice = ecx. expr_vec_slice ( sp , pieces) ;
451
455
let st = ast:: ItemStatic ( ty, ast:: MutImmutable , slice) ;
452
456
453
457
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) ) ;
456
460
457
461
// 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) ) ) )
461
465
}
462
466
463
467
/// Actually builds the expression which the iformat! block will be expanded
@@ -497,7 +501,7 @@ impl<'a, 'b> Context<'a, 'b> {
497
501
498
502
let name = self . ecx . ident_of ( & format ! ( "__arg{}" , i) ) ;
499
503
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,
501
505
self . ecx . expr_ident ( e. span , name) ) ) ;
502
506
heads. push ( self . ecx . expr_addr_of ( e. span , e) ) ;
503
507
}
@@ -515,7 +519,7 @@ impl<'a, 'b> Context<'a, 'b> {
515
519
* name) ) ;
516
520
pats. push ( self . ecx . pat_ident ( e. span , lname) ) ;
517
521
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,
519
523
self . ecx . expr_ident ( e. span , lname) ) ) ;
520
524
heads. push ( self . ecx . expr_addr_of ( e. span , e) ) ;
521
525
}
@@ -566,7 +570,7 @@ impl<'a, 'b> Context<'a, 'b> {
566
570
// Build up the static array which will store our precompiled
567
571
// nonstandard placeholders, if there are any.
568
572
let piece_ty = self . ecx . ty_path ( self . ecx . path_global (
569
- self . fmtsp ,
573
+ self . macsp ,
570
574
Context :: rtpath ( self . ecx , "Argument" ) ) ) ;
571
575
let fmt = Context :: static_array ( self . ecx ,
572
576
"__STATIC_FMTARGS" ,
@@ -576,14 +580,14 @@ impl<'a, 'b> Context<'a, 'b> {
576
580
( "new_v1_formatted" , vec ! [ pieces, args_slice, fmt] )
577
581
} ;
578
582
579
- self . ecx . expr_call_global ( self . fmtsp , vec ! (
583
+ self . ecx . expr_call_global ( self . macsp , vec ! (
580
584
self . ecx. ident_of_std( "core" ) ,
581
585
self . ecx. ident_of( "fmt" ) ,
582
586
self . ecx. ident_of( "Arguments" ) ,
583
587
self . ecx. ident_of( fn_name) ) , fn_args)
584
588
}
585
589
586
- fn format_arg ( ecx : & ExtCtxt , sp : Span ,
590
+ fn format_arg ( ecx : & ExtCtxt , macsp : Span , sp : Span ,
587
591
ty : & ArgumentType , arg : P < ast:: Expr > )
588
592
-> P < ast:: Expr > {
589
593
let trait_ = match * ty {
@@ -607,7 +611,7 @@ impl<'a, 'b> Context<'a, 'b> {
607
611
}
608
612
}
609
613
Unsigned => {
610
- return ecx. expr_call_global ( sp , vec ! [
614
+ return ecx. expr_call_global ( macsp , vec ! [
611
615
ecx. ident_of_std( "core" ) ,
612
616
ecx. ident_of( "fmt" ) ,
613
617
ecx. ident_of( "ArgumentV1" ) ,
@@ -620,7 +624,7 @@ impl<'a, 'b> Context<'a, 'b> {
620
624
ecx. ident_of( "fmt" ) ,
621
625
ecx. ident_of( trait_) ,
622
626
ecx. ident_of( "fmt" ) ] ) ;
623
- ecx. expr_call_global ( sp , vec ! [
627
+ ecx. expr_call_global ( macsp , vec ! [
624
628
ecx. ident_of_std( "core" ) ,
625
629
ecx. ident_of( "fmt" ) ,
626
630
ecx. ident_of( "ArgumentV1" ) ,
@@ -650,6 +654,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span,
650
654
names : HashMap < String , P < ast:: Expr > > )
651
655
-> P < ast:: Expr > {
652
656
let arg_types: Vec < _ > = ( 0 ..args. len ( ) ) . map ( |_| None ) . collect ( ) ;
657
+ let macsp = ecx. call_site ( ) ;
653
658
// Expand the format literal so that efmt.span will have a backtrace. This
654
659
// is essential for locating a bug when the format literal is generated in
655
660
// 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,
668
673
pieces : Vec :: new ( ) ,
669
674
str_pieces : Vec :: new ( ) ,
670
675
all_pieces_simple : true ,
676
+ macsp : macsp,
671
677
fmtsp : efmt. span ,
672
678
} ;
673
679
let fmt = match expr_to_string ( cx. ecx ,
0 commit comments