Ignore imported items in min_ident_chars

Suppress the `min_ident_chars` warning for items whose name we cannot
control. Do not warn for `use a::b`, but warn for `use a::b as c`, since
`c` is a local identifier.

Fixes #12232
This commit is contained in:
Ethiraric 2024-02-12 23:16:47 +01:00
parent 7dfa6ced9b
commit c1c2c3e60c
4 changed files with 58 additions and 15 deletions

View File

@ -3,7 +3,7 @@ use clippy_utils::is_from_proc_macro;
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def::{DefKind, Res}; use rustc_hir::def::{DefKind, Res};
use rustc_hir::intravisit::{walk_item, Visitor}; use rustc_hir::intravisit::{walk_item, Visitor};
use rustc_hir::{GenericParamKind, HirId, Item, ItemKind, ItemLocalId, Node, Pat, PatKind}; use rustc_hir::{GenericParamKind, HirId, Item, ItemKind, ItemLocalId, Node, Pat, PatKind, UsePath};
use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro; use rustc_middle::lint::in_external_macro;
use rustc_session::impl_lint_pass; use rustc_session::impl_lint_pass;
@ -105,11 +105,26 @@ impl Visitor<'_> for IdentVisitor<'_, '_> {
let str = ident.as_str(); let str = ident.as_str();
if conf.is_ident_too_short(cx, str, ident.span) { if conf.is_ident_too_short(cx, str, ident.span) {
if let Node::Item(item) = node // Check whether the node is part of a `use` statement. We don't want to emit a warning if the user
&& let ItemKind::Use(..) = item.kind // has no control over the type.
let usenode = opt_as_use_node(node).or_else(|| {
cx.tcx
.hir()
.parent_iter(hir_id)
.find_map(|(_, node)| opt_as_use_node(node))
});
// If the name of the identifier is the same as the one of the imported item, this means that we
// found a `use foo::bar`. We can early-return to not emit the warning.
// If however the identifier is different, this means it is an alias (`use foo::bar as baz`). In
// this case, we need to emit the warning for `baz`.
if let Some(imported_item_path) = usenode
&& let Some(Res::Def(_, imported_item_defid)) = imported_item_path.res.first()
&& cx.tcx.item_name(*imported_item_defid).as_str() == str
{ {
return; return;
} }
// `struct Awa<T>(T)` // `struct Awa<T>(T)`
// ^ // ^
if let Node::PathSegment(path) = node { if let Node::PathSegment(path) = node {
@ -160,3 +175,16 @@ fn emit_min_ident_chars(conf: &MinIdentChars, cx: &impl LintContext, ident: &str
}; };
span_lint(cx, MIN_IDENT_CHARS, span, &help); span_lint(cx, MIN_IDENT_CHARS, span, &help);
} }
/// Attempt to convert the node to an [`ItemKind::Use`] node.
///
/// If it is, return the [`UsePath`] contained within.
fn opt_as_use_node(node: Node<'_>) -> Option<&'_ UsePath<'_>> {
if let Node::Item(item) = node
&& let ItemKind::Use(path, _) = item.kind
{
Some(path)
} else {
None
}
}

View File

@ -1,3 +1,9 @@
#![allow(nonstandard_style, unused)] #![allow(nonstandard_style, unused)]
pub struct Aaa; pub struct Aaa;
pub struct Bbb;
pub const N: u32 = 3;
pub const M: u32 = 2;
pub const LONGER: u32 = 32;

View File

@ -3,7 +3,10 @@
#![warn(clippy::min_ident_chars)] #![warn(clippy::min_ident_chars)]
extern crate extern_types; extern crate extern_types;
use extern_types::Aaa; use extern_types::{Aaa, LONGER, M, N as W};
pub const N: u32 = 0;
pub const LONG: u32 = 32;
struct Owo { struct Owo {
Uwu: u128, Uwu: u128,

View File

@ -1,47 +1,53 @@
error: this ident is too short (3 <= 3) error: this ident is too short (1 <= 3)
--> $DIR/min_ident_chars.rs:6:19 --> $DIR/min_ident_chars.rs:6:41
| |
LL | use extern_types::Aaa; LL | use extern_types::{Aaa, LONGER, M, N as W};
| ^^^ | ^
| |
= note: `-D clippy::min-ident-chars` implied by `-D warnings` = note: `-D clippy::min-ident-chars` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::min_ident_chars)]` = help: to override `-D warnings` add `#[allow(clippy::min_ident_chars)]`
error: this ident is too short (1 <= 3)
--> $DIR/min_ident_chars.rs:8:11
|
LL | pub const N: u32 = 0;
| ^
error: this ident is too short (3 <= 3) error: this ident is too short (3 <= 3)
--> $DIR/min_ident_chars.rs:10:5 --> $DIR/min_ident_chars.rs:13:5
| |
LL | aaa: Aaa, LL | aaa: Aaa,
| ^^^ | ^^^
error: this ident is too short (3 <= 3) error: this ident is too short (3 <= 3)
--> $DIR/min_ident_chars.rs:15:9 --> $DIR/min_ident_chars.rs:18:9
| |
LL | let vvv = 1; LL | let vvv = 1;
| ^^^ | ^^^
error: this ident is too short (3 <= 3) error: this ident is too short (3 <= 3)
--> $DIR/min_ident_chars.rs:16:9 --> $DIR/min_ident_chars.rs:19:9
| |
LL | let uuu = 1; LL | let uuu = 1;
| ^^^ | ^^^
error: this ident is too short (1 <= 3) error: this ident is too short (1 <= 3)
--> $DIR/min_ident_chars.rs:17:14 --> $DIR/min_ident_chars.rs:20:14
| |
LL | let (mut a, mut b) = (1, 2); LL | let (mut a, mut b) = (1, 2);
| ^ | ^
error: this ident is too short (1 <= 3) error: this ident is too short (1 <= 3)
--> $DIR/min_ident_chars.rs:17:21 --> $DIR/min_ident_chars.rs:20:21
| |
LL | let (mut a, mut b) = (1, 2); LL | let (mut a, mut b) = (1, 2);
| ^ | ^
error: this ident is too short (1 <= 3) error: this ident is too short (1 <= 3)
--> $DIR/min_ident_chars.rs:18:9 --> $DIR/min_ident_chars.rs:21:9
| |
LL | for i in 0..1000 {} LL | for i in 0..1000 {}
| ^ | ^
error: aborting due to 7 previous errors error: aborting due to 8 previous errors