@@ -2,7 +2,7 @@ use super::LoweringContext;
22use  rustc_ast as  ast; 
33use  rustc_ast:: visit:: { self ,  Visitor } ; 
44use  rustc_ast:: * ; 
5- use  rustc_data_structures:: fx:: FxIndexSet ; 
5+ use  rustc_data_structures:: fx:: FxIndexMap ; 
66use  rustc_hir as  hir; 
77use  rustc_span:: { 
88    sym, 
@@ -238,7 +238,7 @@ fn make_count<'hir>(
238238    ctx :  & mut  LoweringContext < ' _ ,  ' hir > , 
239239    sp :  Span , 
240240    count :  & Option < FormatCount > , 
241-     argmap :  & mut  FxIndexSet < ( usize ,  ArgumentType ) > , 
241+     argmap :  & mut  FxIndexMap < ( usize ,  ArgumentType ) ,   Option < Span > > , 
242242)  -> hir:: Expr < ' hir >  { 
243243    match  count { 
244244        Some ( FormatCount :: Literal ( n) )  => { 
@@ -252,7 +252,7 @@ fn make_count<'hir>(
252252        } 
253253        Some ( FormatCount :: Argument ( arg) )  => { 
254254            if  let  Ok ( arg_index)  = arg. index  { 
255-                 let  ( i,  _)  = argmap. insert_full ( ( arg_index,  ArgumentType :: Usize ) ) ; 
255+                 let  ( i,  _)  = argmap. insert_full ( ( arg_index,  ArgumentType :: Usize ) ,  arg . span ) ; 
256256                let  count_param = ctx. arena . alloc ( ctx. expr_lang_item_type_relative ( 
257257                    sp, 
258258                    hir:: LangItem :: FormatCount , 
@@ -291,12 +291,14 @@ fn make_format_spec<'hir>(
291291    ctx :  & mut  LoweringContext < ' _ ,  ' hir > , 
292292    sp :  Span , 
293293    placeholder :  & FormatPlaceholder , 
294-     argmap :  & mut  FxIndexSet < ( usize ,  ArgumentType ) > , 
294+     argmap :  & mut  FxIndexMap < ( usize ,  ArgumentType ) ,   Option < Span > > , 
295295)  -> hir:: Expr < ' hir >  { 
296296    let  position = match  placeholder. argument . index  { 
297297        Ok ( arg_index)  => { 
298-             let  ( i,  _)  =
299-                 argmap. insert_full ( ( arg_index,  ArgumentType :: Format ( placeholder. format_trait ) ) ) ; 
298+             let  ( i,  _)  = argmap. insert_full ( 
299+                 ( arg_index,  ArgumentType :: Format ( placeholder. format_trait ) ) , 
300+                 placeholder. span , 
301+             ) ; 
300302            ctx. expr_usize ( sp,  i) 
301303        } 
302304        Err ( _)  => ctx. expr ( 
@@ -386,15 +388,18 @@ fn expand_format_args<'hir>(
386388
387389    // Create a list of all _unique_ (argument, format trait) combinations. 
388390    // E.g. "{0} {0:x} {0} {1}" -> [(0, Display), (0, LowerHex), (1, Display)] 
389-     let  mut  argmap = FxIndexSet :: default ( ) ; 
391+     let  mut  argmap = FxIndexMap :: default ( ) ; 
390392    for  piece in  & fmt. template  { 
391393        let  FormatArgsPiece :: Placeholder ( placeholder)  = piece else  {  continue  } ; 
392394        if  placeholder. format_options  != Default :: default ( )  { 
393395            // Can't use basic form if there's any formatting options. 
394396            use_format_options = true ; 
395397        } 
396398        if  let  Ok ( index)  = placeholder. argument . index  { 
397-             if  !argmap. insert ( ( index,  ArgumentType :: Format ( placeholder. format_trait ) ) )  { 
399+             if  argmap
400+                 . insert ( ( index,  ArgumentType :: Format ( placeholder. format_trait ) ) ,  placeholder. span ) 
401+                 . is_some ( ) 
402+             { 
398403                // Duplicate (argument, format trait) combination, 
399404                // which we'll only put once in the args array. 
400405                use_format_options = true ; 
@@ -438,7 +443,7 @@ fn expand_format_args<'hir>(
438443    // This is an optimization, speeding up compilation about 1-2% in some cases. 
439444    // See https://github.com/rust-lang/rust/pull/106770#issuecomment-1380790609 
440445    let  use_simple_array = argmap. len ( )  == arguments. len ( ) 
441-         && argmap. iter ( ) . enumerate ( ) . all ( |( i,  & ( j,  _) ) | i == j) 
446+         && argmap. iter ( ) . enumerate ( ) . all ( |( i,  ( & ( j,  _ ) ,  _) ) | i == j) 
442447        && arguments. iter ( ) . skip ( 1 ) . all ( |arg| !may_contain_yield_point ( & arg. expr ) ) ; 
443448
444449    let  args = if  use_simple_array { 
@@ -452,14 +457,19 @@ fn expand_format_args<'hir>(
452457        let  elements:  Vec < _ >  = arguments
453458            . iter ( ) 
454459            . zip ( argmap) 
455-             . map ( |( arg,  ( _,  ty) ) | { 
456-                 let  sp = arg. expr . span . with_ctxt ( macsp. ctxt ( ) ) ; 
460+             . map ( |( arg,  ( ( _,  ty) ,  placeholder_span) ) | { 
461+                 let  placeholder_span =
462+                     placeholder_span. unwrap_or ( arg. expr . span ) . with_ctxt ( macsp. ctxt ( ) ) ; 
463+                 let  arg_span = match  arg. kind  { 
464+                     FormatArgumentKind :: Captured ( _)  => placeholder_span, 
465+                     _ => arg. expr . span . with_ctxt ( macsp. ctxt ( ) ) , 
466+                 } ; 
457467                let  arg = ctx. lower_expr ( & arg. expr ) ; 
458468                let  ref_arg = ctx. arena . alloc ( ctx. expr ( 
459-                     sp , 
469+                     arg_span , 
460470                    hir:: ExprKind :: AddrOf ( hir:: BorrowKind :: Ref ,  hir:: Mutability :: Not ,  arg) , 
461471                ) ) ; 
462-                 make_argument ( ctx,  sp ,  ref_arg,  ty) 
472+                 make_argument ( ctx,  placeholder_span ,  ref_arg,  ty) 
463473            } ) 
464474            . collect ( ) ; 
465475        ctx. expr_array_ref ( macsp,  ctx. arena . alloc_from_iter ( elements) ) 
@@ -475,16 +485,26 @@ fn expand_format_args<'hir>(
475485        //     } 
476486        let  args_ident = Ident :: new ( sym:: args,  macsp) ; 
477487        let  ( args_pat,  args_hir_id)  = ctx. pat_ident ( macsp,  args_ident) ; 
478-         let  args = ctx. arena . alloc_from_iter ( argmap. iter ( ) . map ( |& ( arg_index,  ty) | { 
479-             let  arg = & arguments[ arg_index] ; 
480-             let  sp = arg. expr . span . with_ctxt ( macsp. ctxt ( ) ) ; 
481-             let  args_ident_expr = ctx. expr_ident ( macsp,  args_ident,  args_hir_id) ; 
482-             let  arg = ctx. arena . alloc ( ctx. expr ( 
483-                 sp, 
484-                 hir:: ExprKind :: Field ( args_ident_expr,  Ident :: new ( sym:: integer ( arg_index) ,  macsp) ) , 
485-             ) ) ; 
486-             make_argument ( ctx,  sp,  arg,  ty) 
487-         } ) ) ; 
488+         let  args = ctx. arena . alloc_from_iter ( argmap. iter ( ) . map ( 
489+             |( & ( arg_index,  ty) ,  & placeholder_span) | { 
490+                 let  arg = & arguments[ arg_index] ; 
491+                 let  placeholder_span =
492+                     placeholder_span. unwrap_or ( arg. expr . span ) . with_ctxt ( macsp. ctxt ( ) ) ; 
493+                 let  arg_span = match  arg. kind  { 
494+                     FormatArgumentKind :: Captured ( _)  => placeholder_span, 
495+                     _ => arg. expr . span . with_ctxt ( macsp. ctxt ( ) ) , 
496+                 } ; 
497+                 let  args_ident_expr = ctx. expr_ident ( macsp,  args_ident,  args_hir_id) ; 
498+                 let  arg = ctx. arena . alloc ( ctx. expr ( 
499+                     arg_span, 
500+                     hir:: ExprKind :: Field ( 
501+                         args_ident_expr, 
502+                         Ident :: new ( sym:: integer ( arg_index) ,  macsp) , 
503+                     ) , 
504+                 ) ) ; 
505+                 make_argument ( ctx,  placeholder_span,  arg,  ty) 
506+             } , 
507+         ) ) ; 
488508        let  elements:  Vec < _ >  = arguments
489509            . iter ( ) 
490510            . map ( |arg| { 
0 commit comments