@@ -111,8 +111,10 @@ struct Context<'a, 'b: 'a> {
111
111
/// still existed in this phase of processing.
112
112
/// Used only for `all_pieces_simple` tracking in `build_piece`.
113
113
curarg : usize ,
114
+ curpiece : usize ,
114
115
/// Keep track of invalid references to positional arguments
115
116
invalid_refs : Vec < usize > ,
117
+ arg_spans : Vec < Span > ,
116
118
}
117
119
118
120
/// Parses the arguments from the given list of tokens, returning None
@@ -235,6 +237,7 @@ impl<'a, 'b> Context<'a, 'b> {
235
237
236
238
let ty = Placeholder ( arg. format . ty . to_string ( ) ) ;
237
239
self . verify_arg_type ( pos, ty) ;
240
+ self . curpiece += 1 ;
238
241
}
239
242
}
240
243
}
@@ -347,7 +350,9 @@ impl<'a, 'b> Context<'a, 'b> {
347
350
Some ( e) => * e,
348
351
None => {
349
352
let msg = format ! ( "there is no argument named `{}`" , name) ;
350
- self . ecx . span_err ( self . fmtsp , & msg[ ..] ) ;
353
+ let sp = * self . arg_spans . get ( self . curpiece ) . unwrap_or ( & self . fmtsp ) ;
354
+ let mut err = self . ecx . struct_span_err ( sp, & msg[ ..] ) ;
355
+ err. emit ( ) ;
351
356
return ;
352
357
}
353
358
} ;
@@ -773,6 +778,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
773
778
arg_unique_types,
774
779
names,
775
780
curarg : 0 ,
781
+ curpiece : 0 ,
776
782
arg_index_map : Vec :: new ( ) ,
777
783
count_args : Vec :: new ( ) ,
778
784
count_positions : HashMap :: new ( ) ,
@@ -785,6 +791,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
785
791
macsp,
786
792
fmtsp : fmt. span ,
787
793
invalid_refs : Vec :: new ( ) ,
794
+ arg_spans : Vec :: new ( ) ,
788
795
} ;
789
796
790
797
let fmt_str = & * fmt. node . 0 . as_str ( ) ;
@@ -793,12 +800,22 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
793
800
ast:: StrStyle :: Raw ( raw) => Some ( raw as usize ) ,
794
801
} ;
795
802
let mut parser = parse:: Parser :: new ( fmt_str, str_style) ;
803
+ let mut unverified_pieces = vec ! [ ] ;
796
804
let mut pieces = vec ! [ ] ;
797
805
798
- while let Some ( mut piece) = parser. next ( ) {
806
+ while let Some ( piece) = parser. next ( ) {
799
807
if !parser. errors . is_empty ( ) {
800
808
break ;
801
809
}
810
+ unverified_pieces. push ( piece) ;
811
+ }
812
+
813
+ cx. arg_spans = parser. arg_places . iter ( )
814
+ . map ( |& ( start, end) | fmt. span . from_inner_byte_pos ( start, end) )
815
+ . collect ( ) ;
816
+
817
+ // This needs to happen *after* the Parser has consumed all pieces to create all the spans
818
+ for mut piece in unverified_pieces {
802
819
cx. verify_piece ( & piece) ;
803
820
cx. resolve_name_inplace ( & mut piece) ;
804
821
pieces. push ( piece) ;
0 commit comments