@@ -772,8 +772,10 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
772
772
// `ArgumentType` does not derive `Clone`.
773
773
let arg_types: Vec < _ > = ( 0 ..args. len ( ) ) . map ( |_| Vec :: new ( ) ) . collect ( ) ;
774
774
let arg_unique_types: Vec < _ > = ( 0 ..args. len ( ) ) . map ( |_| Vec :: new ( ) ) . collect ( ) ;
775
+
775
776
let mut macsp = ecx. call_site ( ) ;
776
777
macsp = macsp. apply_mark ( ecx. current_expansion . mark ) ;
778
+
777
779
let msg = "format argument must be a string literal" ;
778
780
let fmt_sp = efmt. span ;
779
781
let fmt = match expr_to_spanned_string ( ecx, efmt, msg) {
@@ -796,11 +798,46 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
796
798
return DummyResult :: raw_expr ( sp) ;
797
799
}
798
800
} ;
801
+
799
802
let is_literal = match ecx. codemap ( ) . span_to_snippet ( fmt_sp) {
800
803
Ok ( ref s) if s. starts_with ( "\" " ) || s. starts_with ( "r#" ) => true ,
801
804
_ => false ,
802
805
} ;
803
806
807
+ let fmt_str = & * fmt. node . 0 . as_str ( ) ;
808
+ let str_style = match fmt. node . 1 {
809
+ ast:: StrStyle :: Cooked => None ,
810
+ ast:: StrStyle :: Raw ( raw) => Some ( raw as usize ) ,
811
+ } ;
812
+
813
+ let mut parser = parse:: Parser :: new ( fmt_str, str_style) ;
814
+
815
+ let mut unverified_pieces = Vec :: new ( ) ;
816
+ while let Some ( piece) = parser. next ( ) {
817
+ if !parser. errors . is_empty ( ) {
818
+ break ;
819
+ } else {
820
+ unverified_pieces. push ( piece) ;
821
+ }
822
+ }
823
+
824
+ if !parser. errors . is_empty ( ) {
825
+ let err = parser. errors . remove ( 0 ) ;
826
+ let sp = fmt. span . from_inner_byte_pos ( err. start , err. end ) ;
827
+ let mut e = ecx. struct_span_err ( sp, & format ! ( "invalid format string: {}" ,
828
+ err. description) ) ;
829
+ e. span_label ( sp, err. label + " in format string" ) ;
830
+ if let Some ( note) = err. note {
831
+ e. note ( & note) ;
832
+ }
833
+ e. emit ( ) ;
834
+ return DummyResult :: raw_expr ( sp) ;
835
+ }
836
+
837
+ let arg_spans = parser. arg_places . iter ( )
838
+ . map ( |& ( start, end) | fmt. span . from_inner_byte_pos ( start, end) )
839
+ . collect ( ) ;
840
+
804
841
let mut cx = Context {
805
842
ecx,
806
843
args,
@@ -815,42 +852,22 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
815
852
count_positions_count : 0 ,
816
853
count_args_index_offset : 0 ,
817
854
literal : String :: new ( ) ,
818
- pieces : Vec :: new ( ) ,
819
- str_pieces : Vec :: new ( ) ,
855
+ pieces : Vec :: with_capacity ( unverified_pieces . len ( ) ) ,
856
+ str_pieces : Vec :: with_capacity ( unverified_pieces . len ( ) ) ,
820
857
all_pieces_simple : true ,
821
858
macsp,
822
859
fmtsp : fmt. span ,
823
860
invalid_refs : Vec :: new ( ) ,
824
- arg_spans : Vec :: new ( ) ,
861
+ arg_spans,
825
862
is_literal,
826
863
} ;
827
864
828
- let fmt_str = & * fmt. node . 0 . as_str ( ) ;
829
- let str_style = match fmt. node . 1 {
830
- ast:: StrStyle :: Cooked => None ,
831
- ast:: StrStyle :: Raw ( raw) => Some ( raw as usize ) ,
832
- } ;
833
- let mut parser = parse:: Parser :: new ( fmt_str, str_style) ;
834
- let mut unverified_pieces = vec ! [ ] ;
835
- let mut pieces = vec ! [ ] ;
836
-
837
- while let Some ( piece) = parser. next ( ) {
838
- if !parser. errors . is_empty ( ) {
839
- break ;
840
- }
841
- unverified_pieces. push ( piece) ;
842
- }
843
-
844
- cx. arg_spans = parser. arg_places . iter ( )
845
- . map ( |& ( start, end) | fmt. span . from_inner_byte_pos ( start, end) )
846
- . collect ( ) ;
847
-
848
865
// This needs to happen *after* the Parser has consumed all pieces to create all the spans
849
- for mut piece in unverified_pieces {
866
+ let pieces = unverified_pieces. into_iter ( ) . map ( | mut piece| {
850
867
cx. verify_piece ( & piece) ;
851
868
cx. resolve_name_inplace ( & mut piece) ;
852
- pieces . push ( piece) ;
853
- }
869
+ piece
870
+ } ) . collect :: < Vec < _ > > ( ) ;
854
871
855
872
let numbered_position_args = pieces. iter ( ) . any ( |arg : & parse:: Piece | {
856
873
match * arg {
@@ -867,6 +884,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
867
884
cx. build_index_map ( ) ;
868
885
869
886
let mut arg_index_consumed = vec ! [ 0usize ; cx. arg_index_map. len( ) ] ;
887
+
870
888
for piece in pieces {
871
889
if let Some ( piece) = cx. build_piece ( & piece, & mut arg_index_consumed) {
872
890
let s = cx. build_literal_string ( ) ;
@@ -875,18 +893,6 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
875
893
}
876
894
}
877
895
878
- if !parser. errors . is_empty ( ) {
879
- let err = parser. errors . remove ( 0 ) ;
880
- let sp = cx. fmtsp . from_inner_byte_pos ( err. start , err. end ) ;
881
- let mut e = cx. ecx . struct_span_err ( sp, & format ! ( "invalid format string: {}" ,
882
- err. description) ) ;
883
- e. span_label ( sp, err. label + " in format string" ) ;
884
- if let Some ( note) = err. note {
885
- e. note ( & note) ;
886
- }
887
- e. emit ( ) ;
888
- return DummyResult :: raw_expr ( sp) ;
889
- }
890
896
if !cx. literal . is_empty ( ) {
891
897
let s = cx. build_literal_string ( ) ;
892
898
cx. str_pieces . push ( s) ;
@@ -898,24 +904,25 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
898
904
899
905
// Make sure that all arguments were used and all arguments have types.
900
906
let num_pos_args = cx. args . len ( ) - cx. names . len ( ) ;
901
- let mut errs = vec ! [ ] ;
902
- for ( i, ty) in cx. arg_types . iter ( ) . enumerate ( ) {
903
- if ty. len ( ) == 0 {
904
- if cx. count_positions . contains_key ( & i) {
905
- continue ;
906
- }
907
- let msg = if i >= num_pos_args {
908
- // named argument
909
- "named argument never used"
910
- } else {
911
- // positional argument
912
- "argument never used"
913
- } ;
914
- errs. push ( ( cx. args [ i] . span , msg) ) ;
915
- }
916
- }
907
+
908
+ let errs = cx. arg_types
909
+ . iter ( )
910
+ . enumerate ( )
911
+ . filter ( |( i, ty) | ty. is_empty ( ) && !cx. count_positions . contains_key ( & i) )
912
+ . map ( |( i, _) | {
913
+ let msg = if i >= num_pos_args {
914
+ // named argument
915
+ "named argument never used"
916
+ } else {
917
+ // positional argument
918
+ "argument never used"
919
+ } ;
920
+ ( cx. args [ i] . span , msg)
921
+ } )
922
+ . collect :: < Vec < _ > > ( ) ;
923
+
917
924
let errs_len = errs. len ( ) ;
918
- if errs_len > 0 {
925
+ if !errs . is_empty ( ) {
919
926
let args_used = cx. arg_types . len ( ) - errs_len;
920
927
let args_unused = errs_len;
921
928
0 commit comments