Skip to content

Commit b97ad4e

Browse files
committed
Add const parameter REPLACEMENT_ALLOWED to DisallowedPath
1 parent d0f3577 commit b97ad4e

File tree

6 files changed

+67
-18
lines changed

6 files changed

+67
-18
lines changed

clippy_config/src/conf.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,7 @@ define_Conf! {
445445
avoid_breaking_exported_api: bool = true,
446446
/// The list of types which may not be held across an await point.
447447
#[lints(await_holding_invalid_type)]
448-
await_holding_invalid_types: Vec<DisallowedPath> = Vec::new(),
448+
await_holding_invalid_types: Vec<DisallowedPath<false>> = Vec::new(),
449449
/// DEPRECATED LINT: BLACKLISTED_NAME.
450450
///
451451
/// Use the Disallowed Names lint instead

clippy_config/src/types.rs

Lines changed: 44 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,33 @@ pub struct Rename {
1414
pub rename: String,
1515
}
1616

17-
#[derive(Debug, Deserialize)]
17+
#[derive(Debug, Serialize)]
18+
pub struct DisallowedPath<const REPLACEMENT_ALLOWED: bool = true> {
19+
path: String,
20+
reason: Option<String>,
21+
replacement: Option<String>,
22+
}
23+
24+
impl<'de, const REPLACEMENT_ALLOWED: bool> Deserialize<'de> for DisallowedPath<REPLACEMENT_ALLOWED> {
25+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
26+
where
27+
D: Deserializer<'de>,
28+
{
29+
let enum_ = DisallowedPathEnum::deserialize(deserializer)?;
30+
if !REPLACEMENT_ALLOWED && enum_.replacement().is_some() {
31+
return Err(de::Error::custom("replacement not allowed for this configuration"));
32+
}
33+
Ok(Self {
34+
path: enum_.path().to_owned(),
35+
reason: enum_.reason().map(ToOwned::to_owned),
36+
replacement: enum_.replacement().map(ToOwned::to_owned),
37+
})
38+
}
39+
}
40+
41+
#[derive(Debug, Deserialize, Serialize)]
1842
#[serde(untagged)]
19-
pub enum DisallowedPath {
43+
pub enum DisallowedPathEnum {
2044
Simple(String),
2145
WithReason {
2246
path: String,
@@ -25,27 +49,33 @@ pub enum DisallowedPath {
2549
},
2650
}
2751

28-
impl DisallowedPath {
52+
impl<const REPLACEMENT_ALLOWED: bool> DisallowedPath<REPLACEMENT_ALLOWED> {
2953
pub fn path(&self) -> &str {
30-
let (Self::Simple(path) | Self::WithReason { path, .. }) = self;
31-
32-
path
54+
&self.path
3355
}
3456

35-
pub fn diag_amendment(&self, span: Span) -> impl FnOnce(&mut Diag<'_, ()>) + use<'_> {
57+
pub fn diag_amendment(&self, span: Span) -> impl FnOnce(&mut Diag<'_, ()>) + use<'_, REPLACEMENT_ALLOWED> {
3658
move |diag| {
37-
if let Some(replacement) = self.replacement() {
59+
if let Some(replacement) = &self.replacement {
3860
diag.span_suggestion(
3961
span,
40-
self.reason().map_or_else(|| String::from("use"), ToOwned::to_owned),
62+
self.reason.as_ref().map_or_else(|| String::from("use"), Clone::clone),
4163
replacement,
4264
Applicability::MachineApplicable,
4365
);
44-
} else if let Some(reason) = self.reason() {
45-
diag.note(reason.to_owned());
66+
} else if let Some(reason) = &self.reason {
67+
diag.note(reason.clone());
4668
}
4769
}
4870
}
71+
}
72+
73+
impl DisallowedPathEnum {
74+
pub fn path(&self) -> &str {
75+
let (Self::Simple(path) | Self::WithReason { path, .. }) = self;
76+
77+
path
78+
}
4979

5080
fn reason(&self) -> Option<&str> {
5181
match &self {
@@ -63,10 +93,10 @@ impl DisallowedPath {
6393
}
6494

6595
/// Creates a map of disallowed items to the reason they were disallowed.
66-
pub fn create_disallowed_map(
96+
pub fn create_disallowed_map<const REPLACEMENT_ALLOWED: bool>(
6797
tcx: TyCtxt<'_>,
68-
disallowed: &'static [DisallowedPath],
69-
) -> DefIdMap<(&'static str, &'static DisallowedPath)> {
98+
disallowed: &'static [DisallowedPath<REPLACEMENT_ALLOWED>],
99+
) -> DefIdMap<(&'static str, &'static DisallowedPath<REPLACEMENT_ALLOWED>)> {
70100
disallowed
71101
.iter()
72102
.map(|x| (x.path(), x.path().split("::").collect::<Vec<_>>(), x))
@@ -466,7 +496,6 @@ macro_rules! unimplemented_serialize {
466496
}
467497

468498
unimplemented_serialize! {
469-
DisallowedPath,
470499
Rename,
471500
MacroMatcher,
472501
}

clippy_lints/src/await_holding_invalid.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ declare_clippy_lint! {
174174
impl_lint_pass!(AwaitHolding => [AWAIT_HOLDING_LOCK, AWAIT_HOLDING_REFCELL_REF, AWAIT_HOLDING_INVALID_TYPE]);
175175

176176
pub struct AwaitHolding {
177-
def_ids: DefIdMap<(&'static str, &'static DisallowedPath)>,
177+
def_ids: DefIdMap<(&'static str, &'static DisallowedPath<false>)>,
178178
}
179179

180180
impl AwaitHolding {
@@ -255,7 +255,12 @@ impl AwaitHolding {
255255
}
256256
}
257257

258-
fn emit_invalid_type(cx: &LateContext<'_>, span: Span, path: &'static str, disallowed_path: &'static DisallowedPath) {
258+
fn emit_invalid_type(
259+
cx: &LateContext<'_>,
260+
span: Span,
261+
path: &'static str,
262+
disallowed_path: &'static DisallowedPath<false>,
263+
) {
259264
span_lint_and_then(
260265
cx,
261266
AWAIT_HOLDING_INVALID_TYPE,
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
fn main() {}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error: error reading Clippy's configuration file: replacement not allowed for this configuration
2+
--> $DIR/tests/ui-toml/await_holding_invalid_type_with_replacement/clippy.toml:1:31
3+
|
4+
LL | await-holding-invalid-types = [
5+
| _______________________________^
6+
LL | | { path = "std::string::String", replacement = "std::net::Ipv4Addr" },
7+
LL | | ]
8+
| |_^
9+
10+
error: aborting due to 1 previous error
11+
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
await-holding-invalid-types = [
2+
{ path = "std::string::String", replacement = "std::net::Ipv4Addr" },
3+
]

0 commit comments

Comments
 (0)