@@ -146,16 +146,13 @@ fn parse_args<'a>(
146
146
if p. token == token:: Eof {
147
147
break ;
148
148
} // accept trailing commas
149
- if named || ( p. token . is_ident ( ) && p. look_ahead ( 1 , |t| * t == token:: Eq ) ) {
149
+ if p. token . is_ident ( ) && p. look_ahead ( 1 , |t| * t == token:: Eq ) {
150
150
named = true ;
151
151
let name = if let token:: Ident ( name, _) = p. token . kind {
152
152
p. bump ( ) ;
153
153
name
154
154
} else {
155
- return Err ( ecx. struct_span_err (
156
- p. token . span ,
157
- "expected ident, positional arguments cannot follow named arguments" ,
158
- ) ) ;
155
+ unreachable ! ( ) ;
159
156
} ;
160
157
161
158
p. expect ( & token:: Eq ) ?;
@@ -176,6 +173,17 @@ fn parse_args<'a>(
176
173
args. push ( e) ;
177
174
} else {
178
175
let e = p. parse_expr ( ) ?;
176
+ if named {
177
+ let mut err = ecx. struct_span_err (
178
+ e. span ,
179
+ "positional arguments cannot follow named arguments" ,
180
+ ) ;
181
+ err. span_label ( e. span , "positional arguments must be before named arguments" ) ;
182
+ for ( _, pos) in & names {
183
+ err. span_label ( args[ * pos] . span , "named argument" ) ;
184
+ }
185
+ err. emit ( ) ;
186
+ }
179
187
args. push ( e) ;
180
188
}
181
189
}
@@ -721,13 +729,14 @@ pub fn expand_format_args_nl<'cx>(
721
729
722
730
/// Take the various parts of `format_args!(efmt, args..., name=names...)`
723
731
/// and construct the appropriate formatting expression.
724
- pub fn expand_preparsed_format_args ( ecx : & mut ExtCtxt < ' _ > ,
725
- sp : Span ,
726
- efmt : P < ast:: Expr > ,
727
- args : Vec < P < ast:: Expr > > ,
728
- names : FxHashMap < Symbol , usize > ,
729
- append_newline : bool )
730
- -> P < ast:: Expr > {
732
+ pub fn expand_preparsed_format_args (
733
+ ecx : & mut ExtCtxt < ' _ > ,
734
+ sp : Span ,
735
+ efmt : P < ast:: Expr > ,
736
+ args : Vec < P < ast:: Expr > > ,
737
+ names : FxHashMap < Symbol , usize > ,
738
+ append_newline : bool ,
739
+ ) -> P < ast:: Expr > {
731
740
// NOTE: this verbose way of initializing `Vec<Vec<ArgumentType>>` is because
732
741
// `ArgumentType` does not derive `Clone`.
733
742
let arg_types: Vec < _ > = ( 0 ..args. len ( ) ) . map ( |_| Vec :: new ( ) ) . collect ( ) ;
@@ -906,6 +915,8 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt<'_>,
906
915
. map ( |span| fmt. span . from_inner ( * span) )
907
916
. collect ( ) ;
908
917
918
+ let named_pos: FxHashSet < usize > = names. values ( ) . cloned ( ) . collect ( ) ;
919
+
909
920
let mut cx = Context {
910
921
ecx,
911
922
args,
@@ -971,14 +982,12 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt<'_>,
971
982
}
972
983
973
984
// Make sure that all arguments were used and all arguments have types.
974
- let num_pos_args = cx. args . len ( ) - cx. names . len ( ) ;
975
-
976
985
let errs = cx. arg_types
977
986
. iter ( )
978
987
. enumerate ( )
979
988
. filter ( |( i, ty) | ty. is_empty ( ) && !cx. count_positions . contains_key ( & i) )
980
989
. map ( |( i, _) | {
981
- let msg = if i >= num_pos_args {
990
+ let msg = if named_pos . contains ( & i ) {
982
991
// named argument
983
992
"named argument never used"
984
993
} else {
0 commit comments