@@ -50,7 +50,8 @@ struct Context<'a, 'b:'a> {
50
50
/// Named expressions are resolved early, and are appended to the end of
51
51
/// argument expressions.
52
52
args : Vec < P < ast:: Expr > > ,
53
- arg_types : Vec < Vec < ArgumentType > > ,
53
+ arg_types : Vec < Vec < usize > > ,
54
+ arg_unique_types : Vec < Vec < ArgumentType > > ,
54
55
/// Map from named arguments to their resolved indices.
55
56
names : HashMap < String , usize > ,
56
57
@@ -69,7 +70,7 @@ struct Context<'a, 'b:'a> {
69
70
/// corresponding to each positional argument, and number of references
70
71
/// consumed so far for each argument, to facilitate correct `Position`
71
72
/// mapping in `trans_piece`.
72
- arg_index_map : Vec < usize > ,
73
+ arg_index_map : Vec < Vec < usize > > ,
73
74
74
75
count_args_index_offset : usize ,
75
76
@@ -234,7 +235,17 @@ impl<'a, 'b> Context<'a, 'b> {
234
235
}
235
236
match ty {
236
237
Placeholder ( _) => {
237
- self . arg_types [ arg] . push ( ty) ;
238
+ // record every (position, type) combination only once
239
+ let ref mut seen_ty = self . arg_unique_types [ arg] ;
240
+ let i = match seen_ty. iter ( ) . position ( |x| * x == ty) {
241
+ Some ( i) => i,
242
+ None => {
243
+ let i = seen_ty. len ( ) ;
244
+ seen_ty. push ( ty) ;
245
+ i
246
+ }
247
+ } ;
248
+ self . arg_types [ arg] . push ( i) ;
238
249
}
239
250
Count => {
240
251
match self . count_positions . entry ( arg) {
@@ -274,8 +285,13 @@ impl<'a, 'b> Context<'a, 'b> {
274
285
275
286
// Generate mapping for positional args
276
287
for i in 0 ..args_len {
277
- self . arg_index_map . push ( sofar) ;
278
- sofar += self . arg_types [ i] . len ( ) ;
288
+ let ref arg_types = self . arg_types [ i] ;
289
+ let mut arg_offsets = Vec :: with_capacity ( arg_types. len ( ) ) ;
290
+ for offset in arg_types {
291
+ arg_offsets. push ( sofar + * offset) ;
292
+ }
293
+ self . arg_index_map . push ( arg_offsets) ;
294
+ sofar += self . arg_unique_types [ i] . len ( ) ;
279
295
}
280
296
281
297
// Record starting index for counts, which appear just
@@ -355,12 +371,13 @@ impl<'a, 'b> Context<'a, 'b> {
355
371
parse:: ArgumentIs ( i) => {
356
372
// Map to index in final generated argument array
357
373
// in case of multiple types specified
358
- let arg_idx = if self . args . len ( ) > i {
359
- let arg_idx = self . arg_index_map [ i] + arg_index_consumed[ i] ;
360
- arg_index_consumed[ i] += 1 ;
361
- arg_idx
362
- } else {
363
- 0 // error already emitted elsewhere
374
+ let arg_idx = match arg_index_consumed. get_mut ( i) {
375
+ None => 0 , // error already emitted elsewhere
376
+ Some ( offset) => {
377
+ let arg_idx = self . arg_index_map [ i] [ * offset] ;
378
+ * offset += 1 ;
379
+ arg_idx
380
+ }
364
381
} ;
365
382
pos ( "At" , Some ( arg_idx) )
366
383
}
@@ -490,7 +507,7 @@ impl<'a, 'b> Context<'a, 'b> {
490
507
for ( i, e) in self . args . into_iter ( ) . enumerate ( ) {
491
508
let name = self . ecx . ident_of ( & format ! ( "__arg{}" , i) ) ;
492
509
pats. push ( self . ecx . pat_ident ( DUMMY_SP , name) ) ;
493
- for ref arg_ty in self . arg_types [ i] . iter ( ) {
510
+ for ref arg_ty in self . arg_unique_types [ i] . iter ( ) {
494
511
locals. push ( Context :: format_arg ( self . ecx , self . macsp , e. span , arg_ty,
495
512
self . ecx . expr_ident ( e. span , name) ) ) ;
496
513
}
@@ -626,6 +643,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span,
626
643
names : HashMap < String , usize > )
627
644
-> P < ast:: Expr > {
628
645
let arg_types: Vec < _ > = ( 0 ..args. len ( ) ) . map ( |_| Vec :: new ( ) ) . collect ( ) ;
646
+ let arg_unique_types: Vec < _ > = ( 0 ..args. len ( ) ) . map ( |_| Vec :: new ( ) ) . collect ( ) ;
629
647
let macsp = ecx. call_site ( ) ;
630
648
// Expand the format literal so that efmt.span will have a backtrace. This
631
649
// is essential for locating a bug when the format literal is generated in
@@ -635,6 +653,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span,
635
653
ecx : ecx,
636
654
args : args,
637
655
arg_types : arg_types,
656
+ arg_unique_types : arg_unique_types,
638
657
names : names,
639
658
curarg : 0 ,
640
659
arg_index_map : Vec :: new ( ) ,
0 commit comments