@@ -8,8 +8,9 @@ use serde::de::{Deserializer, IgnoredAny, IntoDeserializer, MapAccess, Visitor};
88use serde:: Deserialize ;
99use std:: fmt:: { Debug , Display , Formatter } ;
1010use std:: ops:: Range ;
11- use std:: path:: { Path , PathBuf } ;
11+ use std:: path:: PathBuf ;
1212use std:: str:: FromStr ;
13+ use std:: sync:: OnceLock ;
1314use std:: { cmp, env, fmt, fs, io} ;
1415
1516#[ rustfmt:: skip]
@@ -78,62 +79,35 @@ pub struct TryConf {
7879
7980impl TryConf {
8081 fn from_toml_error ( file : & SourceFile , error : & toml:: de:: Error ) -> Self {
81- ConfError :: from_toml ( file, error) . into ( )
82- }
83- }
84-
85- impl From < ConfError > for TryConf {
86- fn from ( value : ConfError ) -> Self {
8782 Self {
8883 conf : Conf :: default ( ) ,
89- errors : vec ! [ value ] ,
84+ errors : vec ! [ ConfError :: from_toml ( file , error ) ] ,
9085 warnings : vec ! [ ] ,
9186 }
9287 }
9388}
9489
95- impl From < io:: Error > for TryConf {
96- fn from ( value : io:: Error ) -> Self {
97- ConfError :: from ( value) . into ( )
98- }
99- }
100-
10190#[ derive( Debug ) ]
10291pub struct ConfError {
10392 pub message : String ,
104- pub span : Option < Span > ,
93+ pub span : Span ,
10594}
10695
10796impl ConfError {
10897 fn from_toml ( file : & SourceFile , error : & toml:: de:: Error ) -> Self {
109- if let Some ( span) = error. span ( ) {
110- Self :: spanned ( file, error. message ( ) , span)
111- } else {
112- Self {
113- message : error. message ( ) . to_string ( ) ,
114- span : None ,
115- }
116- }
98+ let span = error. span ( ) . unwrap_or ( 0 ..file. source_len . 0 as usize ) ;
99+ Self :: spanned ( file, error. message ( ) , span)
117100 }
118101
119102 fn spanned ( file : & SourceFile , message : impl Into < String > , span : Range < usize > ) -> Self {
120103 Self {
121104 message : message. into ( ) ,
122- span : Some ( Span :: new (
105+ span : Span :: new (
123106 file. start_pos + BytePos :: from_usize ( span. start ) ,
124107 file. start_pos + BytePos :: from_usize ( span. end ) ,
125108 SyntaxContext :: root ( ) ,
126109 None ,
127- ) ) ,
128- }
129- }
130- }
131-
132- impl From < io:: Error > for ConfError {
133- fn from ( value : io:: Error ) -> Self {
134- Self {
135- message : value. to_string ( ) ,
136- span : None ,
110+ ) ,
137111 }
138112 }
139113}
@@ -297,7 +271,7 @@ define_Conf! {
297271 /// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, OPTION_MAP_UNWRAP_OR, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION, COLLAPSIBLE_STR_REPLACE, SEEK_FROM_CURRENT, SEEK_REWIND, UNNECESSARY_LAZY_EVALUATIONS, TRANSMUTE_PTR_TO_REF, ALMOST_COMPLETE_RANGE, NEEDLESS_BORROW, DERIVABLE_IMPLS, MANUAL_IS_ASCII_CHECK, MANUAL_REM_EUCLID, MANUAL_RETAIN, TYPE_REPETITION_IN_BOUNDS, TUPLE_ARRAY_CONVERSIONS, MANUAL_TRY_FOLD, MANUAL_HASH_ONE.
298272 ///
299273 /// The minimum rust version that the project supports
300- ( msrv: Option < String > = None ) ,
274+ ( msrv: crate :: Msrv = crate :: Msrv :: empty ( ) ) ,
301275 /// DEPRECATED LINT: BLACKLISTED_NAME.
302276 ///
303277 /// Use the Disallowed Names lint instead
@@ -641,15 +615,8 @@ pub fn lookup_conf_file() -> io::Result<(Option<PathBuf>, Vec<String>)> {
641615 }
642616}
643617
644- /// Read the `toml` configuration file.
645- ///
646- /// In case of error, the function tries to continue as much as possible.
647- pub fn read ( sess : & Session , path : & Path ) -> TryConf {
648- let file = match sess. source_map ( ) . load_file ( path) {
649- Err ( e) => return e. into ( ) ,
650- Ok ( file) => file,
651- } ;
652- match toml:: de:: Deserializer :: new ( file. src . as_ref ( ) . unwrap ( ) ) . deserialize_map ( ConfVisitor ( & file) ) {
618+ fn deserialize ( file : & SourceFile ) -> TryConf {
619+ match toml:: de:: Deserializer :: new ( file. src . as_ref ( ) . unwrap ( ) ) . deserialize_map ( ConfVisitor ( file) ) {
653620 Ok ( mut conf) => {
654621 extend_vec_if_indicator_present ( & mut conf. conf . doc_valid_idents , DEFAULT_DOC_VALID_IDENTS ) ;
655622 extend_vec_if_indicator_present ( & mut conf. conf . disallowed_names , DEFAULT_DISALLOWED_NAMES ) ;
@@ -662,7 +629,7 @@ pub fn read(sess: &Session, path: &Path) -> TryConf {
662629
663630 conf
664631 } ,
665- Err ( e) => TryConf :: from_toml_error ( & file, & e) ,
632+ Err ( e) => TryConf :: from_toml_error ( file, & e) ,
666633 }
667634}
668635
@@ -672,6 +639,60 @@ fn extend_vec_if_indicator_present(vec: &mut Vec<String>, default: &[&str]) {
672639 }
673640}
674641
642+ impl Conf {
643+ pub fn read ( sess : & Session , path : & io:: Result < ( Option < PathBuf > , Vec < String > ) > ) -> & ' static Conf {
644+ static CONF : OnceLock < Conf > = OnceLock :: new ( ) ;
645+ CONF . get_or_init ( || Conf :: read_inner ( sess, path) )
646+ }
647+
648+ fn read_inner ( sess : & Session , path : & io:: Result < ( Option < PathBuf > , Vec < String > ) > ) -> Conf {
649+ match path {
650+ Ok ( ( _, warnings) ) => {
651+ for warning in warnings {
652+ sess. warn ( warning. clone ( ) ) ;
653+ }
654+ } ,
655+ Err ( error) => {
656+ sess. err ( format ! ( "error finding Clippy's configuration file: {error}" ) ) ;
657+ } ,
658+ }
659+
660+ let TryConf {
661+ mut conf,
662+ errors,
663+ warnings,
664+ } = match path {
665+ Ok ( ( Some ( path) , _) ) => match sess. source_map ( ) . load_file ( path) {
666+ Ok ( file) => deserialize ( & file) ,
667+ Err ( error) => {
668+ sess. err ( format ! ( "failed to read `{}`: {error}" , path. display( ) ) ) ;
669+ TryConf :: default ( )
670+ } ,
671+ } ,
672+ _ => TryConf :: default ( ) ,
673+ } ;
674+
675+ conf. msrv . read_cargo ( sess) ;
676+
677+ // all conf errors are non-fatal, we just use the default conf in case of error
678+ for error in errors {
679+ sess. span_err (
680+ error. span ,
681+ format ! ( "error reading Clippy's configuration file: {}" , error. message) ,
682+ ) ;
683+ }
684+
685+ for warning in warnings {
686+ sess. span_warn (
687+ warning. span ,
688+ format ! ( "error reading Clippy's configuration file: {}" , warning. message) ,
689+ ) ;
690+ }
691+
692+ conf
693+ }
694+ }
695+
675696const SEPARATOR_WIDTH : usize = 4 ;
676697
677698#[ derive( Debug ) ]
0 commit comments