@@ -218,42 +218,53 @@ macro_rules! define_Conf {
218
218
let mut value_spans = HashMap :: new( ) ;
219
219
let mut errors = Vec :: new( ) ;
220
220
let mut warnings = Vec :: new( ) ;
221
+
222
+ // Declare a local variable for each field field available to a configuration file.
221
223
$( let mut $name = None ; ) *
224
+
222
225
// could get `Field` here directly, but get `String` first for diagnostics
223
226
while let Some ( name) = map. next_key:: <toml:: Spanned <String >>( ) ? {
224
- match Field :: deserialize( name. get_ref( ) . as_str( ) . into_deserializer( ) ) {
227
+ let field = match Field :: deserialize( name. get_ref( ) . as_str( ) . into_deserializer( ) ) {
225
228
Err ( e) => {
226
229
let e: FieldError = e;
227
230
errors. push( ConfError :: spanned( self . 0 , e. error, e. suggestion, name. span( ) ) ) ;
231
+ continue ;
228
232
}
229
- $( Ok ( Field :: $name) => {
233
+ Ok ( field) => field
234
+ } ;
235
+
236
+ match field {
237
+ $( Field :: $name => {
238
+ // Is this a deprecated field, i.e., is `$dep` set? If so, push a warning.
230
239
$( warnings. push( ConfError :: spanned( self . 0 , format!( "deprecated field `{}`. {}" , name. get_ref( ) , $dep) , None , name. span( ) ) ) ; ) ?
231
240
let raw_value = map. next_value:: <toml:: Spanned <toml:: Value >>( ) ?;
232
241
let value_span = raw_value. span( ) ;
233
- match <$ty>:: deserialize( raw_value. into_inner( ) ) {
234
- Err ( e) => errors. push( ConfError :: spanned( self . 0 , e. to_string( ) . replace( '\n' , " " ) . trim( ) , None , value_span) ) ,
235
- Ok ( value) => match $name {
236
- Some ( _) => {
237
- errors. push( ConfError :: spanned( self . 0 , format!( "duplicate field `{}`" , name. get_ref( ) ) , None , name. span( ) ) ) ;
238
- }
239
- None => {
240
- $name = Some ( value) ;
241
- value_spans. insert( name. get_ref( ) . as_str( ) . to_string( ) , value_span) ;
242
- // $new_conf is the same as one of the defined `$name`s, so
243
- // this variable is defined in line 2 of this function.
244
- $( match $new_conf {
245
- Some ( _) => errors. push( ConfError :: spanned( self . 0 , concat!(
246
- "duplicate field `" , stringify!( $new_conf) ,
247
- "` (provided as `" , stringify!( $name) , "`)"
248
- ) , None , name. span( ) ) ) ,
249
- None => $new_conf = $name. clone( ) ,
250
- } ) ?
251
- } ,
242
+ let value = match <$ty>:: deserialize( raw_value. into_inner( ) ) {
243
+ Err ( e) => {
244
+ errors. push( ConfError :: spanned( self . 0 , e. to_string( ) . replace( '\n' , " " ) . trim( ) , None , value_span) ) ;
245
+ continue ;
252
246
}
247
+ Ok ( value) => value
248
+ } ;
249
+ // Was this field set previously?
250
+ if $name. is_some( ) {
251
+ errors. push( ConfError :: spanned( self . 0 , format!( "duplicate field `{}`" , name. get_ref( ) ) , None , name. span( ) ) ) ;
252
+ continue ;
253
253
}
254
+ $name = Some ( value) ;
255
+ value_spans. insert( name. get_ref( ) . as_str( ) . to_string( ) , value_span) ;
256
+ // If this is a deprecated field, was the new field (`$new_conf`) set previously?
257
+ // Note that `$new_conf` is one of the defined `$name`s.
258
+ $( match $new_conf {
259
+ Some ( _) => errors. push( ConfError :: spanned( self . 0 , concat!(
260
+ "duplicate field `" , stringify!( $new_conf) ,
261
+ "` (provided as `" , stringify!( $name) , "`)"
262
+ ) , None , name. span( ) ) ) ,
263
+ None => $new_conf = $name. clone( ) ,
264
+ } ) ?
254
265
} ) *
255
266
// ignore contents of the third_party key
256
- Ok ( Field :: third_party) => drop( map. next_value:: <IgnoredAny >( ) )
267
+ Field :: third_party => drop( map. next_value:: <IgnoredAny >( ) )
257
268
}
258
269
}
259
270
let conf = Conf { $( $name: $name. unwrap_or_else( defaults:: $name) , ) * } ;
0 commit comments