@@ -120,12 +120,7 @@ impl ConfError {
120120 Self {
121121 message : message. into ( ) ,
122122 suggestion,
123- span : Span :: new (
124- file. start_pos + BytePos :: from_usize ( span. start ) ,
125- file. start_pos + BytePos :: from_usize ( span. end ) ,
126- SyntaxContext :: root ( ) ,
127- None ,
128- ) ,
123+ span : span_from_toml_range ( file, span) ,
129124 }
130125 }
131126}
@@ -176,11 +171,61 @@ macro_rules! default_text {
176171 } ;
177172}
178173
174+ macro_rules! deserialize {
175+ ( $map: expr, $ty: ty, $errors: expr, $file: expr) => { {
176+ let raw_value = $map. next_value:: <toml:: Spanned <toml:: Value >>( ) ?;
177+ let value_span = raw_value. span( ) ;
178+ let value = match <$ty>:: deserialize( raw_value. into_inner( ) ) {
179+ Err ( e) => {
180+ $errors. push( ConfError :: spanned(
181+ $file,
182+ e. to_string( ) . replace( '\n' , " " ) . trim( ) ,
183+ None ,
184+ value_span,
185+ ) ) ;
186+ continue ;
187+ } ,
188+ Ok ( value) => value,
189+ } ;
190+ ( value, value_span)
191+ } } ;
192+
193+ ( $map: expr, $ty: ty, $errors: expr, $file: expr, $replacements_allowed: expr) => { {
194+ let array = $map. next_value:: <Vec <toml:: Spanned <toml:: Value >>>( ) ?;
195+ let mut disallowed_paths_span = Range {
196+ start: usize :: MAX ,
197+ end: usize :: MIN ,
198+ } ;
199+ let mut disallowed_paths = Vec :: new( ) ;
200+ for raw_value in array {
201+ let value_span = raw_value. span( ) ;
202+ let mut disallowed_path = match DisallowedPath :: <$replacements_allowed>:: deserialize( raw_value. into_inner( ) )
203+ {
204+ Err ( e) => {
205+ $errors. push( ConfError :: spanned(
206+ $file,
207+ e. to_string( ) . replace( '\n' , " " ) . trim( ) ,
208+ None ,
209+ value_span,
210+ ) ) ;
211+ continue ;
212+ } ,
213+ Ok ( disallowed_path) => disallowed_path,
214+ } ;
215+ disallowed_paths_span = union ( & disallowed_paths_span, & value_span) ;
216+ disallowed_path. set_span( span_from_toml_range( $file, value_span) ) ;
217+ disallowed_paths. push( disallowed_path) ;
218+ }
219+ ( disallowed_paths, disallowed_paths_span)
220+ } } ;
221+ }
222+
179223macro_rules! define_Conf {
180224 ( $(
181225 $( #[ doc = $doc: literal] ) +
182226 $( #[ conf_deprecated( $dep: literal, $new_conf: ident) ] ) ?
183227 $( #[ default_text = $default_text: expr] ) ?
228+ $( #[ disallowed_paths_allow_replacements = $replacements_allowed: expr] ) ?
184229 $( #[ lints( $( $for_lints: ident) ,* $( , ) ?) ] ) ?
185230 $name: ident: $ty: ty = $default: expr,
186231 ) * ) => {
@@ -219,7 +264,7 @@ macro_rules! define_Conf {
219264 let mut errors = Vec :: new( ) ;
220265 let mut warnings = Vec :: new( ) ;
221266
222- // Declare a local variable for each field field available to a configuration file.
267+ // Declare a local variable for each field available to a configuration file.
223268 $( let mut $name = None ; ) *
224269
225270 // could get `Field` here directly, but get `String` first for diagnostics
@@ -237,15 +282,8 @@ macro_rules! define_Conf {
237282 $( Field :: $name => {
238283 // Is this a deprecated field, i.e., is `$dep` set? If so, push a warning.
239284 $( warnings. push( ConfError :: spanned( self . 0 , format!( "deprecated field `{}`. {}" , name. get_ref( ) , $dep) , None , name. span( ) ) ) ; ) ?
240- let raw_value = map. next_value:: <toml:: Spanned <toml:: Value >>( ) ?;
241- let value_span = raw_value. span( ) ;
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 ;
246- }
247- Ok ( value) => value
248- } ;
285+ let ( value, value_span) =
286+ deserialize!( map, $ty, errors, self . 0 $( , $replacements_allowed) ?) ;
249287 // Was this field set previously?
250288 if $name. is_some( ) {
251289 errors. push( ConfError :: spanned( self . 0 , format!( "duplicate field `{}`" , name. get_ref( ) ) , None , name. span( ) ) ) ;
@@ -286,6 +324,22 @@ macro_rules! define_Conf {
286324 } ;
287325}
288326
327+ fn union ( x : & Range < usize > , y : & Range < usize > ) -> Range < usize > {
328+ Range {
329+ start : cmp:: min ( x. start , y. start ) ,
330+ end : cmp:: max ( x. end , y. end ) ,
331+ }
332+ }
333+
334+ fn span_from_toml_range ( file : & SourceFile , span : Range < usize > ) -> Span {
335+ Span :: new (
336+ file. start_pos + BytePos :: from_usize ( span. start ) ,
337+ file. start_pos + BytePos :: from_usize ( span. end ) ,
338+ SyntaxContext :: root ( ) ,
339+ None ,
340+ )
341+ }
342+
289343define_Conf ! {
290344 /// Which crates to allow absolute paths from
291345 #[ lints( absolute_paths) ]
@@ -472,6 +526,7 @@ define_Conf! {
472526 ) ]
473527 avoid_breaking_exported_api: bool = true ,
474528 /// The list of types which may not be held across an await point.
529+ #[ disallowed_paths_allow_replacements = false ]
475530 #[ lints( await_holding_invalid_type) ]
476531 await_holding_invalid_types: Vec <DisallowedPathWithoutReplacement > = Vec :: new( ) ,
477532 /// DEPRECATED LINT: BLACKLISTED_NAME.
@@ -517,9 +572,11 @@ define_Conf! {
517572 #[ conf_deprecated( "Please use `cognitive-complexity-threshold` instead" , cognitive_complexity_threshold) ]
518573 cyclomatic_complexity_threshold: u64 = 25 ,
519574 /// The list of disallowed macros, written as fully qualified paths.
575+ #[ disallowed_paths_allow_replacements = true ]
520576 #[ lints( disallowed_macros) ]
521577 disallowed_macros: Vec <DisallowedPath > = Vec :: new( ) ,
522578 /// The list of disallowed methods, written as fully qualified paths.
579+ #[ disallowed_paths_allow_replacements = true ]
523580 #[ lints( disallowed_methods) ]
524581 disallowed_methods: Vec <DisallowedPath > = Vec :: new( ) ,
525582 /// The list of disallowed names to lint about. NB: `bar` is not here since it has legitimate uses. The value
@@ -528,6 +585,7 @@ define_Conf! {
528585 #[ lints( disallowed_names) ]
529586 disallowed_names: Vec <String > = DEFAULT_DISALLOWED_NAMES . iter( ) . map( ToString :: to_string) . collect( ) ,
530587 /// The list of disallowed types, written as fully qualified paths.
588+ #[ disallowed_paths_allow_replacements = true ]
531589 #[ lints( disallowed_types) ]
532590 disallowed_types: Vec <DisallowedPath > = Vec :: new( ) ,
533591 /// The list of words this lint should not consider as identifiers needing ticks. The value
0 commit comments