@@ -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