@@ -38,6 +38,10 @@ enum Position {
3838
3939struct 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