@@ -14,18 +14,18 @@ use self::Position::*;
1414use fmt_macros as parse;
1515
1616use syntax:: ast;
17- use syntax:: ext:: base:: * ;
1817use syntax:: ext:: base;
18+ use syntax:: ext:: base:: * ;
1919use syntax:: ext:: build:: AstBuilder ;
2020use syntax:: feature_gate;
2121use syntax:: parse:: token;
2222use syntax:: ptr:: P ;
2323use syntax:: symbol:: Symbol ;
24- use syntax_pos:: { Span , MultiSpan , DUMMY_SP } ;
2524use syntax:: tokenstream;
25+ use syntax_pos:: { MultiSpan , Span , DUMMY_SP } ;
2626
27- use std:: collections:: { HashMap , HashSet } ;
2827use std:: collections:: hash_map:: Entry ;
28+ use std:: collections:: { HashMap , HashSet } ;
2929
3030#[ derive( PartialEq ) ]
3131enum ArgumentType {
@@ -111,9 +111,11 @@ struct Context<'a, 'b: 'a> {
111111 /// still existed in this phase of processing.
112112 /// Used only for `all_pieces_simple` tracking in `build_piece`.
113113 curarg : usize ,
114+ /// Current piece being evaluated, used for error reporting.
114115 curpiece : usize ,
115- /// Keep track of invalid references to positional arguments
116- invalid_refs : Vec < usize > ,
116+ /// Keep track of invalid references to positional arguments.
117+ invalid_refs : Vec < ( usize , usize ) > ,
118+ /// Spans of all the formatting arguments, in order.
117119 arg_spans : Vec < Span > ,
118120}
119121
@@ -157,15 +159,20 @@ fn parse_args(ecx: &mut ExtCtxt,
157159 i
158160 }
159161 _ if named => {
160- ecx. span_err ( p. span ,
161- "expected ident, positional arguments \
162- cannot follow named arguments") ;
162+ ecx. span_err (
163+ p. span ,
164+ "expected ident, positional arguments cannot follow named arguments" ,
165+ ) ;
163166 return None ;
164167 }
165168 _ => {
166- ecx. span_err ( p. span ,
167- & format ! ( "expected ident for named argument, found `{}`" ,
168- p. this_token_to_string( ) ) ) ;
169+ ecx. span_err (
170+ p. span ,
171+ & format ! (
172+ "expected ident for named argument, found `{}`" ,
173+ p. this_token_to_string( )
174+ ) ,
175+ ) ;
169176 return None ;
170177 }
171178 } ;
@@ -267,34 +274,47 @@ impl<'a, 'b> Context<'a, 'b> {
267274 /// errors for the case where all arguments are positional and for when
268275 /// there are named arguments or numbered positional arguments in the
269276 /// format string.
270- fn report_invalid_references ( & self , numbered_position_args : bool , arg_places : & [ ( usize , usize ) ] ) {
277+ fn report_invalid_references ( & self , numbered_position_args : bool ) {
271278 let mut e;
272- let sps = arg_places. iter ( )
273- . map ( |& ( start, end) | self . fmtsp . from_inner_byte_pos ( start, end) )
274- . collect :: < Vec < _ > > ( ) ;
275- let sp = MultiSpan :: from_spans ( sps) ;
276- let mut refs: Vec < _ > = self . invalid_refs
279+ let sp = MultiSpan :: from_spans ( self . arg_spans . clone ( ) ) ;
280+ let mut refs: Vec < _ > = self
281+ . invalid_refs
277282 . iter ( )
278- . map ( |r| r. to_string ( ) )
283+ . map ( |( r , pos ) | ( r. to_string ( ) , self . arg_spans . get ( * pos ) ) )
279284 . collect ( ) ;
280285
281286 if self . names . is_empty ( ) && !numbered_position_args {
282- e = self . ecx . mut_span_err ( sp,
283- & format ! ( "{} positional argument{} in format string, but {}" ,
287+ e = self . ecx . mut_span_err (
288+ sp,
289+ & format ! (
290+ "{} positional argument{} in format string, but {}" ,
284291 self . pieces. len( ) ,
285292 if self . pieces. len( ) > 1 { "s" } else { "" } ,
286- self . describe_num_args( ) ) ) ;
293+ self . describe_num_args( )
294+ ) ,
295+ ) ;
287296 } else {
288- let arg_list = match refs. len ( ) {
297+ let ( arg_list, sp ) = match refs. len ( ) {
289298 1 => {
290- let reg = refs. pop ( ) . unwrap ( ) ;
291- format ! ( "argument {}" , reg)
292- } ,
299+ let ( reg, pos) = refs. pop ( ) . unwrap ( ) ;
300+ (
301+ format ! ( "argument {}" , reg) ,
302+ MultiSpan :: from_span ( * pos. unwrap_or ( & self . fmtsp ) ) ,
303+ )
304+ }
293305 _ => {
306+ let pos =
307+ MultiSpan :: from_spans ( refs. iter ( ) . map ( |( _, p) | * p. unwrap ( ) ) . collect ( ) ) ;
308+ let mut refs: Vec < String > = refs. iter ( ) . map ( |( s, _) | s. to_owned ( ) ) . collect ( ) ;
294309 let reg = refs. pop ( ) . unwrap ( ) ;
295- format ! ( "arguments {head} and {tail}" ,
296- tail=reg,
297- head=refs. join( ", " ) )
310+ (
311+ format ! (
312+ "arguments {head} and {tail}" ,
313+ tail = reg,
314+ head = refs. join( ", " )
315+ ) ,
316+ pos,
317+ )
298318 }
299319 } ;
300320
@@ -314,7 +334,7 @@ impl<'a, 'b> Context<'a, 'b> {
314334 match arg {
315335 Exact ( arg) => {
316336 if self . args . len ( ) <= arg {
317- self . invalid_refs . push ( arg) ;
337+ self . invalid_refs . push ( ( arg, self . curpiece ) ) ;
318338 return ;
319339 }
320340 match ty {
@@ -520,33 +540,27 @@ impl<'a, 'b> Context<'a, 'b> {
520540 let prec = self . build_count ( arg. format . precision ) ;
521541 let width = self . build_count ( arg. format . width ) ;
522542 let path = self . ecx . path_global ( sp, Context :: rtpath ( self . ecx , "FormatSpec" ) ) ;
523- let fmt =
524- self . ecx . expr_struct ( sp,
543+ let fmt = self . ecx . expr_struct (
544+ sp,
525545 path,
526- vec ! [ self . ecx
527- . field_imm( sp, self . ecx. ident_of( "fill" ) , fill) ,
528- self . ecx. field_imm( sp,
529- self . ecx. ident_of( "align" ) ,
530- align) ,
531- self . ecx. field_imm( sp,
532- self . ecx. ident_of( "flags" ) ,
533- flags) ,
534- self . ecx. field_imm( sp,
535- self . ecx. ident_of( "precision" ) ,
536- prec) ,
537- self . ecx. field_imm( sp,
538- self . ecx. ident_of( "width" ) ,
539- width) ] ) ;
546+ vec ! [
547+ self . ecx. field_imm( sp, self . ecx. ident_of( "fill" ) , fill) ,
548+ self . ecx. field_imm( sp, self . ecx. ident_of( "align" ) , align) ,
549+ self . ecx. field_imm( sp, self . ecx. ident_of( "flags" ) , flags) ,
550+ self . ecx. field_imm( sp, self . ecx. ident_of( "precision" ) , prec) ,
551+ self . ecx. field_imm( sp, self . ecx. ident_of( "width" ) , width) ,
552+ ] ,
553+ ) ;
540554
541555 let path = self . ecx . path_global ( sp, Context :: rtpath ( self . ecx , "Argument" ) ) ;
542- Some ( self . ecx . expr_struct ( sp,
556+ Some ( self . ecx . expr_struct (
557+ sp,
543558 path,
544- vec ! [ self . ecx. field_imm( sp,
545- self . ecx. ident_of( "position" ) ,
546- pos) ,
547- self . ecx. field_imm( sp,
548- self . ecx. ident_of( "format" ) ,
549- fmt) ] ) )
559+ vec ! [
560+ self . ecx. field_imm( sp, self . ecx. ident_of( "position" ) , pos) ,
561+ self . ecx. field_imm( sp, self . ecx. ident_of( "format" ) , fmt) ,
562+ ] ,
563+ ) )
550564 }
551565 }
552566 }
@@ -559,9 +573,9 @@ impl<'a, 'b> Context<'a, 'b> {
559573 let mut pats = Vec :: new ( ) ;
560574 let mut heads = Vec :: new ( ) ;
561575
562- let names_pos: Vec < _ > = ( 0 ..self . args . len ( ) ) . map ( |i| {
563- self . ecx . ident_of ( & format ! ( "arg{}" , i) ) . gensym ( )
564- } ) . collect ( ) ;
576+ let names_pos: Vec < _ > = ( 0 ..self . args . len ( ) )
577+ . map ( |i| self . ecx . ident_of ( & format ! ( "arg{}" , i) ) . gensym ( ) )
578+ . collect ( ) ;
565579
566580 // First, build up the static array which will become our precompiled
567581 // format "string"
@@ -705,10 +719,11 @@ pub fn expand_format_args<'cx>(ecx: &'cx mut ExtCtxt,
705719 }
706720}
707721
708- pub fn expand_format_args_nl < ' cx > ( ecx : & ' cx mut ExtCtxt ,
722+ pub fn expand_format_args_nl < ' cx > (
723+ ecx : & ' cx mut ExtCtxt ,
709724 mut sp : Span ,
710- tts : & [ tokenstream:: TokenTree ] )
711- -> Box < dyn base:: MacResult + ' cx > {
725+ tts : & [ tokenstream:: TokenTree ] ,
726+ ) -> Box < dyn base:: MacResult + ' cx > {
712727 //if !ecx.ecfg.enable_allow_internal_unstable() {
713728
714729 // For some reason, the only one that actually works for `println` is the first check
@@ -759,7 +774,6 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
759774 let sugg_fmt = match args. len ( ) {
760775 0 => "{}" . to_string ( ) ,
761776 _ => format ! ( "{}{{}}" , "{} " . repeat( args. len( ) ) ) ,
762-
763777 } ;
764778 err. span_suggestion (
765779 fmt_sp. shrink_to_lo ( ) ,
@@ -768,7 +782,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
768782 ) ;
769783 err. emit ( ) ;
770784 return DummyResult :: raw_expr ( sp) ;
771- } ,
785+ }
772786 } ;
773787
774788 let mut cx = Context {
@@ -862,7 +876,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
862876 }
863877
864878 if cx. invalid_refs . len ( ) >= 1 {
865- cx. report_invalid_references ( numbered_position_args, & parser . arg_places ) ;
879+ cx. report_invalid_references ( numbered_position_args) ;
866880 }
867881
868882 // Make sure that all arguments were used and all arguments have types.
@@ -894,7 +908,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
894908 } else {
895909 let mut diag = cx. ecx . struct_span_err (
896910 errs. iter ( ) . map ( |& ( sp, _) | sp) . collect :: < Vec < Span > > ( ) ,
897- "multiple unused formatting arguments"
911+ "multiple unused formatting arguments" ,
898912 ) ;
899913 diag. span_label ( cx. fmtsp , "multiple missing formatting arguments" ) ;
900914 diag
0 commit comments