From f3401bdb96be453416074bb685f7bdfa176a46e1 Mon Sep 17 00:00:00 2001 From: Samuel Moelius Date: Wed, 13 Nov 2024 18:34:08 -0500 Subject: [PATCH] Add const parameter `REPLACEMENT_ALLOWED` to `DisallowedPath` --- clippy_config/src/conf.rs | 2 +- clippy_config/src/types.rs | 53 ++++++++++++++----- clippy_lints/src/await_holding_invalid.rs | 9 +++- clippy_utils/src/lib.rs | 6 +-- .../await_holding_invalid_type.rs | 1 + .../await_holding_invalid_type.stderr | 11 ++++ .../clippy.toml | 3 ++ 7 files changed, 67 insertions(+), 18 deletions(-) create mode 100644 tests/ui-toml/await_holding_invalid_type_with_replacement/await_holding_invalid_type.rs create mode 100644 tests/ui-toml/await_holding_invalid_type_with_replacement/await_holding_invalid_type.stderr create mode 100644 tests/ui-toml/await_holding_invalid_type_with_replacement/clippy.toml diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs index 600d5b6e2c8d..597e6b6a9332 100644 --- a/clippy_config/src/conf.rs +++ b/clippy_config/src/conf.rs @@ -445,7 +445,7 @@ define_Conf! { avoid_breaking_exported_api: bool = true, /// The list of types which may not be held across an await point. #[lints(await_holding_invalid_type)] - await_holding_invalid_types: Vec = Vec::new(), + await_holding_invalid_types: Vec> = Vec::new(), /// DEPRECATED LINT: BLACKLISTED_NAME. /// /// Use the Disallowed Names lint instead diff --git a/clippy_config/src/types.rs b/clippy_config/src/types.rs index 2dfca060cf69..41f38296e6d5 100644 --- a/clippy_config/src/types.rs +++ b/clippy_config/src/types.rs @@ -11,9 +11,33 @@ pub struct Rename { pub rename: String, } -#[derive(Debug, Deserialize)] +#[derive(Debug, Serialize)] +pub struct DisallowedPath { + path: String, + reason: Option, + replacement: Option, +} + +impl<'de, const REPLACEMENT_ALLOWED: bool> Deserialize<'de> for DisallowedPath { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let enum_ = DisallowedPathEnum::deserialize(deserializer)?; + if !REPLACEMENT_ALLOWED && enum_.replacement().is_some() { + return Err(de::Error::custom("replacement not allowed for this configuration")); + } + Ok(Self { + path: enum_.path().to_owned(), + reason: enum_.reason().map(ToOwned::to_owned), + replacement: enum_.replacement().map(ToOwned::to_owned), + }) + } +} + +#[derive(Debug, Deserialize, Serialize)] #[serde(untagged)] -pub enum DisallowedPath { +pub enum DisallowedPathEnum { Simple(String), WithReason { path: String, @@ -22,27 +46,33 @@ pub enum DisallowedPath { }, } -impl DisallowedPath { +impl DisallowedPath { pub fn path(&self) -> &str { - let (Self::Simple(path) | Self::WithReason { path, .. }) = self; - - path + &self.path } - pub fn diag_amendment(&self, span: Span) -> impl FnOnce(&mut Diag<'_, ()>) + use<'_> { + pub fn diag_amendment(&self, span: Span) -> impl FnOnce(&mut Diag<'_, ()>) + use<'_, REPLACEMENT_ALLOWED> { move |diag| { - if let Some(replacement) = self.replacement() { + if let Some(replacement) = &self.replacement { diag.span_suggestion( span, - self.reason().map_or_else(|| String::from("use"), ToOwned::to_owned), + self.reason.as_ref().map_or_else(|| String::from("use"), Clone::clone), replacement, Applicability::MachineApplicable, ); - } else if let Some(reason) = self.reason() { - diag.note(reason.to_owned()); + } else if let Some(reason) = &self.reason { + diag.note(reason.clone()); } } } +} + +impl DisallowedPathEnum { + pub fn path(&self) -> &str { + let (Self::Simple(path) | Self::WithReason { path, .. }) = self; + + path + } fn reason(&self) -> Option<&str> { match &self { @@ -449,7 +479,6 @@ macro_rules! unimplemented_serialize { } unimplemented_serialize! { - DisallowedPath, Rename, MacroMatcher, } diff --git a/clippy_lints/src/await_holding_invalid.rs b/clippy_lints/src/await_holding_invalid.rs index 53b7162a7193..0009e01c5611 100644 --- a/clippy_lints/src/await_holding_invalid.rs +++ b/clippy_lints/src/await_holding_invalid.rs @@ -174,7 +174,7 @@ declare_clippy_lint! { impl_lint_pass!(AwaitHolding => [AWAIT_HOLDING_LOCK, AWAIT_HOLDING_REFCELL_REF, AWAIT_HOLDING_INVALID_TYPE]); pub struct AwaitHolding { - def_ids: DefIdMap<(&'static str, &'static DisallowedPath)>, + def_ids: DefIdMap<(&'static str, &'static DisallowedPath)>, } impl AwaitHolding { @@ -255,7 +255,12 @@ impl AwaitHolding { } } -fn emit_invalid_type(cx: &LateContext<'_>, span: Span, path: &'static str, disallowed_path: &'static DisallowedPath) { +fn emit_invalid_type( + cx: &LateContext<'_>, + span: Span, + path: &'static str, + disallowed_path: &'static DisallowedPath, +) { span_lint_and_then( cx, AWAIT_HOLDING_INVALID_TYPE, diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 59fb1a991f6c..8363f0aee218 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -750,10 +750,10 @@ pub fn def_path_def_ids(tcx: TyCtxt<'_>, path: &[&str]) -> impl Iterator( tcx: TyCtxt<'_>, - disallowed: &'static [DisallowedPath], -) -> DefIdMap<(&'static str, &'static DisallowedPath)> { + disallowed: &'static [DisallowedPath], +) -> DefIdMap<(&'static str, &'static DisallowedPath)> { disallowed .iter() .map(|x| (x.path(), x.path().split("::").collect::>(), x)) diff --git a/tests/ui-toml/await_holding_invalid_type_with_replacement/await_holding_invalid_type.rs b/tests/ui-toml/await_holding_invalid_type_with_replacement/await_holding_invalid_type.rs new file mode 100644 index 000000000000..f328e4d9d04c --- /dev/null +++ b/tests/ui-toml/await_holding_invalid_type_with_replacement/await_holding_invalid_type.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/tests/ui-toml/await_holding_invalid_type_with_replacement/await_holding_invalid_type.stderr b/tests/ui-toml/await_holding_invalid_type_with_replacement/await_holding_invalid_type.stderr new file mode 100644 index 000000000000..86e30409af06 --- /dev/null +++ b/tests/ui-toml/await_holding_invalid_type_with_replacement/await_holding_invalid_type.stderr @@ -0,0 +1,11 @@ +error: error reading Clippy's configuration file: replacement not allowed for this configuration + --> $DIR/tests/ui-toml/await_holding_invalid_type_with_replacement/clippy.toml:1:31 + | +LL | await-holding-invalid-types = [ + | _______________________________^ +LL | | { path = "std::string::String", replacement = "std::net::Ipv4Addr" }, +LL | | ] + | |_^ + +error: aborting due to 1 previous error + diff --git a/tests/ui-toml/await_holding_invalid_type_with_replacement/clippy.toml b/tests/ui-toml/await_holding_invalid_type_with_replacement/clippy.toml new file mode 100644 index 000000000000..f6bc59672ed7 --- /dev/null +++ b/tests/ui-toml/await_holding_invalid_type_with_replacement/clippy.toml @@ -0,0 +1,3 @@ +await-holding-invalid-types = [ + { path = "std::string::String", replacement = "std::net::Ipv4Addr" }, +]