@@ -130,64 +130,46 @@ impl PositionalNamedArgsLint {
130130 /// CountIsParam, which contains an index into the arguments.
131131 fn maybe_add_positional_named_arg (
132132 & mut self ,
133- current_positional_arg : usize ,
134- total_args_length : usize ,
135- format_argument_index : usize ,
133+ arg : Option < & FormatArg > ,
136134 ty : PositionalNamedArgType ,
137135 cur_piece : usize ,
138136 inner_span_to_replace : Option < rustc_parse_format:: InnerSpan > ,
139- names : & FxHashMap < Symbol , ( usize , Span ) > ,
140137 has_formatting : bool ,
141138 ) {
142- let start_of_named_args = total_args_length - names. len ( ) ;
143- if current_positional_arg >= start_of_named_args {
144- self . maybe_push (
145- format_argument_index,
146- ty,
147- cur_piece,
148- inner_span_to_replace,
149- names,
150- has_formatting,
151- )
139+ if let Some ( arg) = arg {
140+ if let Some ( name) = arg. name {
141+ self . push ( name, ty, cur_piece, inner_span_to_replace, has_formatting)
142+ }
152143 }
153144 }
154145
155- /// Try constructing a PositionalNamedArg struct and pushing it into the vec of positional
156- /// named arguments. If a named arg associated with `format_argument_index` cannot be found,
157- /// a new item will not be added as the lint cannot be emitted in this case.
158- fn maybe_push (
146+ /// Construct a PositionalNamedArg struct and push it into the vec of positional
147+ /// named arguments.
148+ fn push (
159149 & mut self ,
160- format_argument_index : usize ,
150+ arg_name : Ident ,
161151 ty : PositionalNamedArgType ,
162152 cur_piece : usize ,
163153 inner_span_to_replace : Option < rustc_parse_format:: InnerSpan > ,
164- names : & FxHashMap < Symbol , ( usize , Span ) > ,
165154 has_formatting : bool ,
166155 ) {
167- let named_arg = names
168- . iter ( )
169- . find ( |& ( _, & ( index, _) ) | index == format_argument_index)
170- . map ( |found| found. clone ( ) ) ;
171-
172- if let Some ( ( & replacement, & ( _, positional_named_arg_span) ) ) = named_arg {
173- // In FormatSpec, `precision_span` starts at the leading `.`, which we want to keep in
174- // the lint suggestion, so increment `start` by 1 when `PositionalArgumentType` is
175- // `Precision`.
176- let inner_span_to_replace = if ty == PositionalNamedArgType :: Precision {
177- inner_span_to_replace
178- . map ( |is| rustc_parse_format:: InnerSpan { start : is. start + 1 , end : is. end } )
179- } else {
180- inner_span_to_replace
181- } ;
182- self . positional_named_args . push ( PositionalNamedArg {
183- ty,
184- cur_piece,
185- inner_span_to_replace,
186- replacement,
187- positional_named_arg_span,
188- has_formatting,
189- } ) ;
190- }
156+ // In FormatSpec, `precision_span` starts at the leading `.`, which we want to keep in
157+ // the lint suggestion, so increment `start` by 1 when `PositionalArgumentType` is
158+ // `Precision`.
159+ let inner_span_to_replace = if ty == PositionalNamedArgType :: Precision {
160+ inner_span_to_replace
161+ . map ( |is| rustc_parse_format:: InnerSpan { start : is. start + 1 , end : is. end } )
162+ } else {
163+ inner_span_to_replace
164+ } ;
165+ self . positional_named_args . push ( PositionalNamedArg {
166+ ty,
167+ cur_piece,
168+ inner_span_to_replace,
169+ replacement : arg_name. name ,
170+ positional_named_arg_span : arg_name. span ,
171+ has_formatting,
172+ } ) ;
191173 }
192174}
193175
@@ -211,15 +193,15 @@ struct Context<'a, 'b> {
211193 /// * `arg_types` (in JSON): `[[0, 1, 0], [0, 1, 1], [0, 1]]`
212194 /// * `arg_unique_types` (in simplified JSON): `[["o", "x"], ["o", "x"], ["o", "x"]]`
213195 /// * `names` (in JSON): `{"foo": 2}`
214- args : Vec < P < ast :: Expr > > ,
196+ args : Vec < FormatArg > ,
215197 /// The number of arguments that were added by implicit capturing.
216198 num_captured_args : usize ,
217199 /// Placeholder slot numbers indexed by argument.
218200 arg_types : Vec < Vec < usize > > ,
219201 /// Unique format specs seen for each argument.
220202 arg_unique_types : Vec < Vec < ArgumentType > > ,
221203 /// Map from named arguments to their resolved indices.
222- names : FxHashMap < Symbol , ( usize , Span ) > ,
204+ names : FxHashMap < Symbol , usize > ,
223205
224206 /// The latest consecutive literal strings, or empty if there weren't any.
225207 literal : String ,
@@ -282,7 +264,7 @@ struct Context<'a, 'b> {
282264
283265pub struct FormatArg {
284266 expr : P < ast:: Expr > ,
285- named : bool ,
267+ name : Option < Ident > ,
286268}
287269
288270/// Parses the arguments from the given list of tokens, returning the diagnostic
@@ -298,9 +280,9 @@ fn parse_args<'a>(
298280 ecx : & mut ExtCtxt < ' a > ,
299281 sp : Span ,
300282 tts : TokenStream ,
301- ) -> PResult < ' a , ( P < ast:: Expr > , Vec < FormatArg > , FxHashMap < Symbol , ( usize , Span ) > ) > {
283+ ) -> PResult < ' a , ( P < ast:: Expr > , Vec < FormatArg > , FxHashMap < Symbol , usize > ) > {
302284 let mut args = Vec :: < FormatArg > :: new ( ) ;
303- let mut names = FxHashMap :: < Symbol , ( usize , Span ) > :: default ( ) ;
285+ let mut names = FxHashMap :: < Symbol , usize > :: default ( ) ;
304286
305287 let mut p = ecx. new_parser_from_tts ( tts) ;
306288
@@ -365,9 +347,9 @@ fn parse_args<'a>(
365347 p. bump ( ) ;
366348 p. expect ( & token:: Eq ) ?;
367349 let e = p. parse_expr ( ) ?;
368- if let Some ( ( prev, _ ) ) = names. get ( & ident. name ) {
350+ if let Some ( & prev) = names. get ( & ident. name ) {
369351 ecx. struct_span_err ( e. span , & format ! ( "duplicate argument named `{}`" , ident) )
370- . span_label ( args[ * prev] . expr . span , "previously here" )
352+ . span_label ( args[ prev] . expr . span , "previously here" )
371353 . span_label ( e. span , "duplicate argument" )
372354 . emit ( ) ;
373355 continue ;
@@ -378,8 +360,8 @@ fn parse_args<'a>(
378360 // if the input is valid, we can simply append to the positional
379361 // args. And remember the names.
380362 let slot = args. len ( ) ;
381- names. insert ( ident. name , ( slot, ident . span ) ) ;
382- args. push ( FormatArg { expr : e, named : true } ) ;
363+ names. insert ( ident. name , slot) ;
364+ args. push ( FormatArg { expr : e, name : Some ( ident ) } ) ;
383365 }
384366 _ => {
385367 let e = p. parse_expr ( ) ?;
@@ -389,12 +371,12 @@ fn parse_args<'a>(
389371 "positional arguments cannot follow named arguments" ,
390372 ) ;
391373 err. span_label ( e. span , "positional arguments must be before named arguments" ) ;
392- for pos in names. values ( ) {
393- err. span_label ( args[ pos. 0 ] . expr . span , "named argument" ) ;
374+ for & pos in names. values ( ) {
375+ err. span_label ( args[ pos] . expr . span , "named argument" ) ;
394376 }
395377 err. emit ( ) ;
396378 }
397- args. push ( FormatArg { expr : e, named : false } ) ;
379+ args. push ( FormatArg { expr : e, name : None } ) ;
398380 }
399381 }
400382 }
@@ -410,8 +392,7 @@ impl<'a, 'b> Context<'a, 'b> {
410392 fn resolve_name_inplace ( & mut self , p : & mut parse:: Piece < ' _ > ) {
411393 // NOTE: the `unwrap_or` branch is needed in case of invalid format
412394 // arguments, e.g., `format_args!("{foo}")`.
413- let lookup =
414- |s : & str | self . names . get ( & Symbol :: intern ( s) ) . unwrap_or ( & ( 0 , Span :: default ( ) ) ) . 0 ;
395+ let lookup = |s : & str | self . names . get ( & Symbol :: intern ( s) ) . copied ( ) . unwrap_or ( 0 ) ;
415396
416397 match * p {
417398 parse:: String ( _) => { }
@@ -457,27 +438,21 @@ impl<'a, 'b> Context<'a, 'b> {
457438 let pos = match arg. position {
458439 parse:: ArgumentIs ( i) => {
459440 self . unused_names_lint . maybe_add_positional_named_arg (
460- i,
461- self . args . len ( ) ,
462- i,
441+ self . args . get ( i) ,
463442 PositionalNamedArgType :: Arg ,
464443 self . curpiece ,
465444 Some ( arg. position_span ) ,
466- & self . names ,
467445 has_precision || has_width,
468446 ) ;
469447
470448 Exact ( i)
471449 }
472450 parse:: ArgumentImplicitlyIs ( i) => {
473451 self . unused_names_lint . maybe_add_positional_named_arg (
474- i,
475- self . args . len ( ) ,
476- i,
452+ self . args . get ( i) ,
477453 PositionalNamedArgType :: Arg ,
478454 self . curpiece ,
479455 None ,
480- & self . names ,
481456 has_precision || has_width,
482457 ) ;
483458 Exact ( i)
@@ -563,13 +538,10 @@ impl<'a, 'b> Context<'a, 'b> {
563538 parse:: CountImplied | parse:: CountIs ( ..) => { }
564539 parse:: CountIsParam ( i) => {
565540 self . unused_names_lint . maybe_add_positional_named_arg (
566- i,
567- self . args . len ( ) ,
568- i,
541+ self . args . get ( i) ,
569542 named_arg_type,
570543 self . curpiece ,
571544 * inner_span,
572- & self . names ,
573545 true ,
574546 ) ;
575547 self . verify_arg_type ( Exact ( i) , Count ) ;
@@ -622,7 +594,7 @@ impl<'a, 'b> Context<'a, 'b> {
622594 ) ;
623595 for arg in & self . args {
624596 // Point at the arguments that will be formatted.
625- e. span_label ( arg. span , "" ) ;
597+ e. span_label ( arg. expr . span , "" ) ;
626598 }
627599 } else {
628600 let ( mut refs, spans) : ( Vec < _ > , Vec < _ > ) = refs. unzip ( ) ;
@@ -692,7 +664,7 @@ impl<'a, 'b> Context<'a, 'b> {
692664 ) ;
693665 if let Some ( arg) = self . args . get ( pos) {
694666 e. span_label (
695- arg. span ,
667+ arg. expr . span ,
696668 "this parameter corresponds to the precision flag" ,
697669 ) ;
698670 }
@@ -771,7 +743,7 @@ impl<'a, 'b> Context<'a, 'b> {
771743 match self . names . get ( & name) {
772744 Some ( & idx) => {
773745 // Treat as positional arg.
774- self . verify_arg_type ( Capture ( idx. 0 ) , ty)
746+ self . verify_arg_type ( Capture ( idx) , ty)
775747 }
776748 None => {
777749 // For the moment capturing variables from format strings expanded from macros is
@@ -787,8 +759,11 @@ impl<'a, 'b> Context<'a, 'b> {
787759 self . fmtsp
788760 } ;
789761 self . num_captured_args += 1 ;
790- self . args . push ( self . ecx . expr_ident ( span, Ident :: new ( name, span) ) ) ;
791- self . names . insert ( name, ( idx, span) ) ;
762+ self . args . push ( FormatArg {
763+ expr : self . ecx . expr_ident ( span, Ident :: new ( name, span) ) ,
764+ name : Some ( Ident :: new ( name, span) ) ,
765+ } ) ;
766+ self . names . insert ( name, idx) ;
792767 self . verify_arg_type ( Capture ( idx) , ty)
793768 } else {
794769 let msg = format ! ( "there is no argument named `{}`" , name) ;
@@ -1054,11 +1029,11 @@ impl<'a, 'b> Context<'a, 'b> {
10541029 // evaluated a single time each, in the order written by the programmer,
10551030 // and that the surrounding future/generator (if any) is Send whenever
10561031 // possible.
1057- let no_need_for_match =
1058- nicely_ordered && !original_args. iter ( ) . skip ( 1 ) . any ( |e | may_contain_yield_point ( e ) ) ;
1032+ let no_need_for_match = nicely_ordered
1033+ && !original_args. iter ( ) . skip ( 1 ) . any ( |arg | may_contain_yield_point ( & arg . expr ) ) ;
10591034
10601035 for ( arg_index, arg_ty) in fmt_arg_index_and_ty {
1061- let e = & mut original_args[ arg_index] ;
1036+ let e = & mut original_args[ arg_index] . expr ;
10621037 let span = e. span ;
10631038 let arg = if no_need_for_match {
10641039 let expansion_span = e. span . with_ctxt ( self . macsp . ctxt ( ) ) ;
@@ -1087,7 +1062,9 @@ impl<'a, 'b> Context<'a, 'b> {
10871062 // span is otherwise unavailable in the MIR used by borrowck).
10881063 let heads = original_args
10891064 . into_iter ( )
1090- . map ( |e| self . ecx . expr_addr_of ( e. span . with_ctxt ( self . macsp . ctxt ( ) ) , e) )
1065+ . map ( |arg| {
1066+ self . ecx . expr_addr_of ( arg. expr . span . with_ctxt ( self . macsp . ctxt ( ) ) , arg. expr )
1067+ } )
10911068 . collect ( ) ;
10921069
10931070 let pat = self . ecx . pat_ident ( self . macsp , Ident :: new ( sym:: args, self . macsp ) ) ;
@@ -1220,7 +1197,7 @@ pub fn expand_preparsed_format_args(
12201197 sp : Span ,
12211198 efmt : P < ast:: Expr > ,
12221199 args : Vec < FormatArg > ,
1223- names : FxHashMap < Symbol , ( usize , Span ) > ,
1200+ names : FxHashMap < Symbol , usize > ,
12241201 append_newline : bool ,
12251202) -> P < ast:: Expr > {
12261203 // NOTE: this verbose way of initializing `Vec<Vec<ArgumentType>>` is because
@@ -1312,16 +1289,17 @@ pub fn expand_preparsed_format_args(
13121289 if err. should_be_replaced_with_positional_argument {
13131290 let captured_arg_span =
13141291 fmt_span. from_inner ( InnerSpan :: new ( err. span . start , err. span . end ) ) ;
1315- let positional_args = args. iter ( ) . filter ( |arg| !arg. named ) . collect :: < Vec < _ > > ( ) ;
1292+ let n_positional_args =
1293+ args. iter ( ) . rposition ( |arg| arg. name . is_none ( ) ) . map_or ( 0 , |i| i + 1 ) ;
13161294 if let Ok ( arg) = ecx. source_map ( ) . span_to_snippet ( captured_arg_span) {
1317- let span = match positional_args . last ( ) {
1295+ let span = match args [ ..n_positional_args ] . last ( ) {
13181296 Some ( arg) => arg. expr . span ,
13191297 None => fmt_sp,
13201298 } ;
13211299 e. multipart_suggestion_verbose (
13221300 "consider using a positional formatting argument instead" ,
13231301 vec ! [
1324- ( captured_arg_span, positional_args . len ( ) . to_string( ) ) ,
1302+ ( captured_arg_span, n_positional_args . to_string( ) ) ,
13251303 ( span. shrink_to_hi( ) , format!( ", {}" , arg) ) ,
13261304 ] ,
13271305 Applicability :: MachineApplicable ,
@@ -1338,11 +1316,9 @@ pub fn expand_preparsed_format_args(
13381316 . map ( |span| fmt_span. from_inner ( InnerSpan :: new ( span. start , span. end ) ) )
13391317 . collect ( ) ;
13401318
1341- let named_pos: FxHashSet < usize > = names. values ( ) . cloned ( ) . map ( |( i, _) | i) . collect ( ) ;
1342-
13431319 let mut cx = Context {
13441320 ecx,
1345- args : args . into_iter ( ) . map ( |arg| arg . expr ) . collect ( ) ,
1321+ args,
13461322 num_captured_args : 0 ,
13471323 arg_types,
13481324 arg_unique_types,
@@ -1410,14 +1386,12 @@ pub fn expand_preparsed_format_args(
14101386 . enumerate ( )
14111387 . filter ( |( i, ty) | ty. is_empty ( ) && !cx. count_positions . contains_key ( & i) )
14121388 . map ( |( i, _) | {
1413- let msg = if named_pos. contains ( & i) {
1414- // named argument
1389+ let msg = if cx. args [ i] . name . is_some ( ) {
14151390 "named argument never used"
14161391 } else {
1417- // positional argument
14181392 "argument never used"
14191393 } ;
1420- ( cx. args [ i] . span , msg)
1394+ ( cx. args [ i] . expr . span , msg)
14211395 } )
14221396 . collect :: < Vec < _ > > ( ) ;
14231397
0 commit comments