Add new lint unneeded_struct_pattern

This commit is contained in:
Asuna 2024-09-27 02:58:14 +08:00
parent 2ddfc92ea2
commit 52abb8f9f0
9 changed files with 660 additions and 2 deletions

View file

@ -445,8 +445,8 @@ fn convert_assoc_item_kind(value: AssocItemKind) -> SourceItemOrderingTraitAssoc
#[allow(clippy::enum_glob_use)] // Very local glob use for legibility.
use SourceItemOrderingTraitAssocItemKind::*;
match value {
AssocItemKind::Const { .. } => Const,
AssocItemKind::Type { .. } => Type,
AssocItemKind::Const => Const,
AssocItemKind::Type => Type,
AssocItemKind::Fn { .. } => Fn,
}
}

View file

@ -753,6 +753,7 @@ pub static LINTS: &[&crate::LintInfo] = &[
crate::unnecessary_self_imports::UNNECESSARY_SELF_IMPORTS_INFO,
crate::unnecessary_struct_initialization::UNNECESSARY_STRUCT_INITIALIZATION_INFO,
crate::unnecessary_wraps::UNNECESSARY_WRAPS_INFO,
crate::unneeded_struct_pattern::UNNEEDED_STRUCT_PATTERN_INFO,
crate::unnested_or_patterns::UNNESTED_OR_PATTERNS_INFO,
crate::unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME_INFO,
crate::unused_async::UNUSED_ASYNC_INFO,

View file

@ -374,6 +374,7 @@ mod unnecessary_owned_empty_strings;
mod unnecessary_self_imports;
mod unnecessary_struct_initialization;
mod unnecessary_wraps;
mod unneeded_struct_pattern;
mod unnested_or_patterns;
mod unsafe_removed_from_name;
mod unused_async;
@ -967,5 +968,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
store.register_late_pass(|_| Box::new(manual_ignore_case_cmp::ManualIgnoreCaseCmp));
store.register_late_pass(|_| Box::new(unnecessary_literal_bound::UnnecessaryLiteralBound));
store.register_late_pass(move |_| Box::new(arbitrary_source_item_ordering::ArbitrarySourceItemOrdering::new(conf)));
store.register_late_pass(|_| Box::new(unneeded_struct_pattern::UnneededStructPattern));
// add lints here, do not remove this comment, it's used in `new_lint`
}

View file

@ -0,0 +1,76 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::is_from_proc_macro;
use rustc_errors::Applicability;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::{Pat, PatKind, QPath};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass;
declare_clippy_lint! {
/// ### What it does
/// Checks for struct patterns that match against unit variant.
///
/// ### Why is this bad?
/// Struct pattern `{ }` or `{ .. }` is not needed for unit variant.
///
/// ### Example
/// ```no_run
/// match Some(42) {
/// Some(v) => v,
/// None { .. } => 0,
/// };
/// // Or
/// match Some(42) {
/// Some(v) => v,
/// None { } => 0,
/// };
/// ```
/// Use instead:
/// ```no_run
/// match Some(42) {
/// Some(v) => v,
/// None => 0,
/// };
/// ```
#[clippy::version = "1.83.0"]
pub UNNEEDED_STRUCT_PATTERN,
style,
"using struct pattern to match against unit variant"
}
declare_lint_pass!(UnneededStructPattern => [UNNEEDED_STRUCT_PATTERN]);
impl LateLintPass<'_> for UnneededStructPattern {
fn check_pat(&mut self, cx: &LateContext<'_>, pat: &Pat<'_>) {
if !pat.span.from_expansion()
&& let PatKind::Struct(path, [], _) = &pat.kind
&& let QPath::Resolved(_, path) = path
&& let Res::Def(DefKind::Variant, did) = path.res
{
let enum_did = cx.tcx.parent(did);
let variant = cx.tcx.adt_def(enum_did).variant_with_id(did);
let has_only_fields_brackets = variant.ctor.is_some() && variant.fields.is_empty();
let non_exhaustive_activated = !variant.def_id.is_local() && variant.is_field_list_non_exhaustive();
if !has_only_fields_brackets || non_exhaustive_activated {
return;
}
if is_from_proc_macro(cx, *path) {
return;
}
if let Some(brackets_span) = pat.span.trim_start(path.span) {
span_lint_and_sugg(
cx,
UNNEEDED_STRUCT_PATTERN,
brackets_span,
"struct pattern is not needed for a unit variant",
"remove the struct pattern",
String::new(),
Applicability::MachineApplicable,
);
}
}
}
}