Skip to content

Commit fc811f7

Browse files
authored
item_name_repetitions: exclude enum variants with identical path components (#14619)
fix #13637 As suggested in the PR above, we should not lint enum variants containing matching path names. changelog: [`item_name_repetitions`]: exclude enum variants with identical path components
2 parents 73dd05c + e89cf4d commit fc811f7

File tree

2 files changed

+41
-2
lines changed

2 files changed

+41
-2
lines changed

clippy_lints/src/item_name_repetitions.rs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use clippy_utils::macros::span_is_local;
55
use clippy_utils::source::is_present_in_source;
66
use clippy_utils::str_utils::{camel_case_split, count_match_end, count_match_start, to_camel_case, to_snake_case};
77
use rustc_data_structures::fx::FxHashSet;
8-
use rustc_hir::{EnumDef, FieldDef, Item, ItemKind, OwnerId, Variant, VariantData};
8+
use rustc_hir::{EnumDef, FieldDef, Item, ItemKind, OwnerId, QPath, TyKind, Variant, VariantData};
99
use rustc_lint::{LateContext, LateLintPass};
1010
use rustc_session::impl_lint_pass;
1111
use rustc_span::symbol::Symbol;
@@ -405,6 +405,7 @@ fn check_enum_start(cx: &LateContext<'_>, item_name: &str, variant: &Variant<'_>
405405
if count_match_start(item_name, name).char_count == item_name_chars
406406
&& name.chars().nth(item_name_chars).is_some_and(|c| !c.is_lowercase())
407407
&& name.chars().nth(item_name_chars + 1).is_some_and(|c| !c.is_numeric())
408+
&& !check_enum_tuple_path_match(name, variant.data)
408409
{
409410
span_lint_hir(
410411
cx,
@@ -420,7 +421,9 @@ fn check_enum_end(cx: &LateContext<'_>, item_name: &str, variant: &Variant<'_>)
420421
let name = variant.ident.name.as_str();
421422
let item_name_chars = item_name.chars().count();
422423

423-
if count_match_end(item_name, name).char_count == item_name_chars {
424+
if count_match_end(item_name, name).char_count == item_name_chars
425+
&& !check_enum_tuple_path_match(name, variant.data)
426+
{
424427
span_lint_hir(
425428
cx,
426429
ENUM_VARIANT_NAMES,
@@ -431,6 +434,27 @@ fn check_enum_end(cx: &LateContext<'_>, item_name: &str, variant: &Variant<'_>)
431434
}
432435
}
433436

437+
/// Checks if an enum tuple variant contains a single field
438+
/// whose qualified path contains the variant's name.
439+
fn check_enum_tuple_path_match(variant_name: &str, variant_data: VariantData<'_>) -> bool {
440+
// Only check single-field tuple variants
441+
let VariantData::Tuple(fields, ..) = variant_data else {
442+
return false;
443+
};
444+
if fields.len() != 1 {
445+
return false;
446+
}
447+
// Check if field type is a path and contains the variant name
448+
match fields[0].ty.kind {
449+
TyKind::Path(QPath::Resolved(_, path)) => path
450+
.segments
451+
.iter()
452+
.any(|segment| segment.ident.name.as_str() == variant_name),
453+
TyKind::Path(QPath::TypeRelative(_, segment)) => segment.ident.name.as_str() == variant_name,
454+
_ => false,
455+
}
456+
}
457+
434458
impl LateLintPass<'_> for ItemNameRepetitions {
435459
fn check_item_post(&mut self, _cx: &LateContext<'_>, item: &Item<'_>) {
436460
let Some(_ident) = item.kind.ident() else { return };

tests/ui/enum_variants.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,4 +220,19 @@ mod issue11494 {
220220
}
221221
}
222222

223+
mod encapsulated {
224+
mod types {
225+
pub struct FooError;
226+
pub struct BarError;
227+
pub struct BazError;
228+
}
229+
230+
enum Error {
231+
FooError(types::FooError),
232+
BarError(types::BarError),
233+
BazError(types::BazError),
234+
Other,
235+
}
236+
}
237+
223238
fn main() {}

0 commit comments

Comments
 (0)