Add const parameter REPLACEMENT_ALLOWED to DisallowedPath
This commit is contained in:
parent
d0f3577720
commit
b97ad4eccd
6 changed files with 74 additions and 25 deletions
|
|
@ -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<DisallowedPath> = Vec::new(),
|
||||
await_holding_invalid_types: Vec<DisallowedPath<false>> = Vec::new(),
|
||||
/// DEPRECATED LINT: BLACKLISTED_NAME.
|
||||
///
|
||||
/// Use the Disallowed Names lint instead
|
||||
|
|
|
|||
|
|
@ -14,9 +14,33 @@ pub struct Rename {
|
|||
pub rename: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct DisallowedPath<const REPLACEMENT_ALLOWED: bool = true> {
|
||||
path: String,
|
||||
reason: Option<String>,
|
||||
replacement: Option<String>,
|
||||
}
|
||||
|
||||
impl<'de, const REPLACEMENT_ALLOWED: bool> Deserialize<'de> for DisallowedPath<REPLACEMENT_ALLOWED> {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
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,
|
||||
|
|
@ -25,28 +49,34 @@ pub enum DisallowedPath {
|
|||
},
|
||||
}
|
||||
|
||||
impl DisallowedPath {
|
||||
impl<const REPLACEMENT_ALLOWED: bool> DisallowedPath<REPLACEMENT_ALLOWED> {
|
||||
pub fn path(&self) -> &str {
|
||||
&self.path
|
||||
}
|
||||
|
||||
pub fn diag_amendment(&self, span: Span) -> impl FnOnce(&mut Diag<'_, ()>) + use<'_, REPLACEMENT_ALLOWED> {
|
||||
move |diag| {
|
||||
if let Some(replacement) = &self.replacement {
|
||||
diag.span_suggestion(
|
||||
span,
|
||||
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.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DisallowedPathEnum {
|
||||
pub fn path(&self) -> &str {
|
||||
let (Self::Simple(path) | Self::WithReason { path, .. }) = self;
|
||||
|
||||
path
|
||||
}
|
||||
|
||||
pub fn diag_amendment(&self, span: Span) -> impl FnOnce(&mut Diag<'_, ()>) + use<'_> {
|
||||
move |diag| {
|
||||
if let Some(replacement) = self.replacement() {
|
||||
diag.span_suggestion(
|
||||
span,
|
||||
self.reason().map_or_else(|| String::from("use"), ToOwned::to_owned),
|
||||
replacement,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else if let Some(reason) = self.reason() {
|
||||
diag.note(reason.to_owned());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn reason(&self) -> Option<&str> {
|
||||
match &self {
|
||||
Self::WithReason { reason, .. } => reason.as_deref(),
|
||||
|
|
@ -63,10 +93,10 @@ impl DisallowedPath {
|
|||
}
|
||||
|
||||
/// Creates a map of disallowed items to the reason they were disallowed.
|
||||
pub fn create_disallowed_map(
|
||||
pub fn create_disallowed_map<const REPLACEMENT_ALLOWED: bool>(
|
||||
tcx: TyCtxt<'_>,
|
||||
disallowed: &'static [DisallowedPath],
|
||||
) -> DefIdMap<(&'static str, &'static DisallowedPath)> {
|
||||
disallowed: &'static [DisallowedPath<REPLACEMENT_ALLOWED>],
|
||||
) -> DefIdMap<(&'static str, &'static DisallowedPath<REPLACEMENT_ALLOWED>)> {
|
||||
disallowed
|
||||
.iter()
|
||||
.map(|x| (x.path(), x.path().split("::").collect::<Vec<_>>(), x))
|
||||
|
|
@ -466,7 +496,6 @@ macro_rules! unimplemented_serialize {
|
|||
}
|
||||
|
||||
unimplemented_serialize! {
|
||||
DisallowedPath,
|
||||
Rename,
|
||||
MacroMatcher,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<false>)>,
|
||||
}
|
||||
|
||||
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<false>,
|
||||
) {
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
AWAIT_HOLDING_INVALID_TYPE,
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
fn main() {}
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
await-holding-invalid-types = [
|
||||
{ path = "std::string::String", replacement = "std::net::Ipv4Addr" },
|
||||
]
|
||||
Loading…
Add table
Add a link
Reference in a new issue