Skip to content

Commit e291bb9

Browse files
committed
Deserialize Msrv directly in Conf
1 parent 2cf708d commit e291bb9

File tree

9 files changed

+116
-167
lines changed

9 files changed

+116
-167
lines changed

clippy_lints/src/lib.rs

+4-61
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,6 @@ extern crate clippy_utils;
5050
#[macro_use]
5151
extern crate declare_clippy_lint;
5252

53-
use std::io;
54-
use std::path::PathBuf;
55-
5653
use clippy_utils::msrvs::Msrv;
5754
use rustc_data_structures::fx::FxHashSet;
5855
use rustc_lint::{Lint, LintId};
@@ -362,7 +359,6 @@ mod zero_sized_map_values;
362359
// end lints modules, do not remove this comment, it’s used in `update_lints`
363360

364361
use crate::utils::conf::metadata::get_configuration_metadata;
365-
use crate::utils::conf::TryConf;
366362
pub use crate::utils::conf::{lookup_conf_file, Conf};
367363
use crate::utils::FindAll;
368364

@@ -374,65 +370,13 @@ use crate::utils::FindAll;
374370
/// level (i.e `#![cfg_attr(...)]`) will still be expanded even when using a pre-expansion pass.
375371
///
376372
/// Used in `./src/driver.rs`.
377-
pub fn register_pre_expansion_lints(store: &mut rustc_lint::LintStore, sess: &Session, conf: &Conf) {
373+
pub fn register_pre_expansion_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
378374
// NOTE: Do not add any more pre-expansion passes. These should be removed eventually.
379-
let msrv = Msrv::read(&conf.msrv, sess);
380-
let msrv = move || msrv.clone();
375+
let msrv = || conf.msrv.clone();
381376

382377
store.register_pre_expansion_pass(move || Box::new(attrs::EarlyAttributes { msrv: msrv() }));
383378
}
384379

385-
#[doc(hidden)]
386-
pub fn read_conf(sess: &Session, path: &io::Result<(Option<PathBuf>, Vec<String>)>) -> Conf {
387-
if let Ok((_, warnings)) = path {
388-
for warning in warnings {
389-
sess.warn(warning.clone());
390-
}
391-
}
392-
let file_name = match path {
393-
Ok((Some(path), _)) => path,
394-
Ok((None, _)) => return Conf::default(),
395-
Err(error) => {
396-
sess.err(format!("error finding Clippy's configuration file: {error}"));
397-
return Conf::default();
398-
},
399-
};
400-
401-
let TryConf { conf, errors, warnings } = utils::conf::read(sess, file_name);
402-
// all conf errors are non-fatal, we just use the default conf in case of error
403-
for error in errors {
404-
if let Some(span) = error.span {
405-
sess.span_err(
406-
span,
407-
format!("error reading Clippy's configuration file: {}", error.message),
408-
);
409-
} else {
410-
sess.err(format!(
411-
"error reading Clippy's configuration file `{}`: {}",
412-
file_name.display(),
413-
error.message
414-
));
415-
}
416-
}
417-
418-
for warning in warnings {
419-
if let Some(span) = warning.span {
420-
sess.span_warn(
421-
span,
422-
format!("error reading Clippy's configuration file: {}", warning.message),
423-
);
424-
} else {
425-
sess.warn(format!(
426-
"error reading Clippy's configuration file `{}`: {}",
427-
file_name.display(),
428-
warning.message
429-
));
430-
}
431-
}
432-
433-
conf
434-
}
435-
436380
#[derive(Default)]
437381
struct RegistrationGroups {
438382
all: Vec<LintId>,
@@ -558,7 +502,7 @@ fn register_categories(store: &mut rustc_lint::LintStore) {
558502
///
559503
/// Used in `./src/driver.rs`.
560504
#[expect(clippy::too_many_lines)]
561-
pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &Conf) {
505+
pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &'static Conf) {
562506
register_removed_non_tool_lints(store);
563507
register_categories(store);
564508

@@ -660,8 +604,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
660604
store.register_late_pass(|_| Box::new(non_octal_unix_permissions::NonOctalUnixPermissions));
661605
store.register_early_pass(|| Box::new(unnecessary_self_imports::UnnecessarySelfImports));
662606

663-
let msrv = Msrv::read(&conf.msrv, sess);
664-
let msrv = move || msrv.clone();
607+
let msrv = || conf.msrv.clone();
665608
let avoid_breaking_exported_api = conf.avoid_breaking_exported_api;
666609
let allow_expect_in_tests = conf.allow_expect_in_tests;
667610
let allow_unwrap_in_tests = conf.allow_unwrap_in_tests;

clippy_lints/src/matches/mod.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -967,7 +967,6 @@ declare_clippy_lint! {
967967
"checks for unnecessary guards in match expressions"
968968
}
969969

970-
#[derive(Default)]
971970
pub struct Matches {
972971
msrv: Msrv,
973972
infallible_destructuring_match_linted: bool,
@@ -978,7 +977,7 @@ impl Matches {
978977
pub fn new(msrv: Msrv) -> Self {
979978
Self {
980979
msrv,
981-
..Matches::default()
980+
infallible_destructuring_match_linted: false,
982981
}
983982
}
984983
}

clippy_lints/src/use_self.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ declare_clippy_lint! {
5454
"unnecessary structure name repetition whereas `Self` is applicable"
5555
}
5656

57-
#[derive(Default)]
5857
pub struct UseSelf {
5958
msrv: Msrv,
6059
stack: Vec<StackItem>,
@@ -65,7 +64,7 @@ impl UseSelf {
6564
pub fn new(msrv: Msrv) -> Self {
6665
Self {
6766
msrv,
68-
..Self::default()
67+
stack: Vec::new(),
6968
}
7069
}
7170
}

clippy_lints/src/utils/conf.rs

+64-43
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ use serde::de::{Deserializer, IgnoredAny, IntoDeserializer, MapAccess, Visitor};
88
use serde::Deserialize;
99
use std::fmt::{Debug, Display, Formatter};
1010
use std::ops::Range;
11-
use std::path::{Path, PathBuf};
11+
use std::path::PathBuf;
1212
use std::str::FromStr;
13+
use std::sync::OnceLock;
1314
use std::{cmp, env, fmt, fs, io};
1415

1516
#[rustfmt::skip]
@@ -78,62 +79,35 @@ pub struct TryConf {
7879

7980
impl 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)]
10291
pub struct ConfError {
10392
pub message: String,
104-
pub span: Option<Span>,
93+
pub span: Span,
10594
}
10695

10796
impl 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::new()),
301275
/// DEPRECATED LINT: BLACKLISTED_NAME.
302276
///
303277
/// Use the Disallowed Names lint instead
@@ -641,14 +615,7 @@ 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-
};
618+
fn deserialize(file: &SourceFile) -> TryConf {
652619
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);
@@ -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+
675696
const SEPARATOR_WIDTH: usize = 4;
676697

677698
#[derive(Debug)]

clippy_utils/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ arrayvec = { version = "0.7", default-features = false }
99
if_chain = "1.0"
1010
itertools = "0.10.1"
1111
rustc-semver = "1.1"
12+
serde = { version = "1.0" }
1213

1314
[features]
1415
deny-warnings = []

0 commit comments

Comments
 (0)