@@ -2,7 +2,7 @@ use super::LoweringContext;
2
2
use rustc_ast as ast;
3
3
use rustc_ast:: visit:: { self , Visitor } ;
4
4
use rustc_ast:: * ;
5
- use rustc_data_structures:: fx:: FxIndexSet ;
5
+ use rustc_data_structures:: fx:: FxIndexMap ;
6
6
use rustc_hir as hir;
7
7
use rustc_span:: {
8
8
sym,
@@ -238,7 +238,7 @@ fn make_count<'hir>(
238
238
ctx : & mut LoweringContext < ' _ , ' hir > ,
239
239
sp : Span ,
240
240
count : & Option < FormatCount > ,
241
- argmap : & mut FxIndexSet < ( usize , ArgumentType ) > ,
241
+ argmap : & mut FxIndexMap < ( usize , ArgumentType ) , Option < Span > > ,
242
242
) -> hir:: Expr < ' hir > {
243
243
match count {
244
244
Some ( FormatCount :: Literal ( n) ) => {
@@ -252,7 +252,7 @@ fn make_count<'hir>(
252
252
}
253
253
Some ( FormatCount :: Argument ( arg) ) => {
254
254
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 ) ;
256
256
let count_param = ctx. arena . alloc ( ctx. expr_lang_item_type_relative (
257
257
sp,
258
258
hir:: LangItem :: FormatCount ,
@@ -291,12 +291,14 @@ fn make_format_spec<'hir>(
291
291
ctx : & mut LoweringContext < ' _ , ' hir > ,
292
292
sp : Span ,
293
293
placeholder : & FormatPlaceholder ,
294
- argmap : & mut FxIndexSet < ( usize , ArgumentType ) > ,
294
+ argmap : & mut FxIndexMap < ( usize , ArgumentType ) , Option < Span > > ,
295
295
) -> hir:: Expr < ' hir > {
296
296
let position = match placeholder. argument . index {
297
297
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
+ ) ;
300
302
ctx. expr_usize ( sp, i)
301
303
}
302
304
Err ( _) => ctx. expr (
@@ -386,15 +388,18 @@ fn expand_format_args<'hir>(
386
388
387
389
// Create a list of all _unique_ (argument, format trait) combinations.
388
390
// 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 ( ) ;
390
392
for piece in & fmt. template {
391
393
let FormatArgsPiece :: Placeholder ( placeholder) = piece else { continue } ;
392
394
if placeholder. format_options != Default :: default ( ) {
393
395
// Can't use basic form if there's any formatting options.
394
396
use_format_options = true ;
395
397
}
396
398
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
+ {
398
403
// Duplicate (argument, format trait) combination,
399
404
// which we'll only put once in the args array.
400
405
use_format_options = true ;
@@ -438,7 +443,7 @@ fn expand_format_args<'hir>(
438
443
// This is an optimization, speeding up compilation about 1-2% in some cases.
439
444
// See https://github.com/rust-lang/rust/pull/106770#issuecomment-1380790609
440
445
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)
442
447
&& arguments. iter ( ) . skip ( 1 ) . all ( |arg| !may_contain_yield_point ( & arg. expr ) ) ;
443
448
444
449
let args = if use_simple_array {
@@ -452,14 +457,19 @@ fn expand_format_args<'hir>(
452
457
let elements: Vec < _ > = arguments
453
458
. iter ( )
454
459
. 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
+ } ;
457
467
let arg = ctx. lower_expr ( & arg. expr ) ;
458
468
let ref_arg = ctx. arena . alloc ( ctx. expr (
459
- sp ,
469
+ arg_span ,
460
470
hir:: ExprKind :: AddrOf ( hir:: BorrowKind :: Ref , hir:: Mutability :: Not , arg) ,
461
471
) ) ;
462
- make_argument ( ctx, sp , ref_arg, ty)
472
+ make_argument ( ctx, placeholder_span , ref_arg, ty)
463
473
} )
464
474
. collect ( ) ;
465
475
ctx. expr_array_ref ( macsp, ctx. arena . alloc_from_iter ( elements) )
@@ -475,16 +485,26 @@ fn expand_format_args<'hir>(
475
485
// }
476
486
let args_ident = Ident :: new ( sym:: args, macsp) ;
477
487
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
+ ) ) ;
488
508
let elements: Vec < _ > = arguments
489
509
. iter ( )
490
510
. map ( |arg| {
0 commit comments