Skip to content

Commit f8da18c

Browse files
authored
Do not mark attributes with unknown namespace as useless (#13766)
Fixes #13764 changelog: [`useless_attribute`]: do not trigger on attributes with unknown namespace
2 parents 0f9cc8d + 092bfef commit f8da18c

File tree

4 files changed

+43
-18
lines changed

4 files changed

+43
-18
lines changed

clippy_lints/src/attrs/useless_attribute.rs

+12-10
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use super::USELESS_ATTRIBUTE;
2-
use super::utils::{extract_clippy_lint, is_lint_level, is_word};
2+
use super::utils::{is_lint_level, is_word, namespace_and_lint};
33
use clippy_utils::diagnostics::span_lint_and_then;
44
use clippy_utils::source::{SpanRangeExt, first_line_of_span};
5-
use rustc_ast::{Attribute, Item, ItemKind, MetaItemInner};
5+
use rustc_ast::{Attribute, Item, ItemKind};
66
use rustc_errors::Applicability;
77
use rustc_lint::{EarlyContext, LintContext};
88
use rustc_middle::lint::in_external_macro;
@@ -20,11 +20,13 @@ pub(super) fn check(cx: &EarlyContext<'_>, item: &Item, attrs: &[Attribute]) {
2020
for lint in lint_list {
2121
match item.kind {
2222
ItemKind::Use(..) => {
23-
if let MetaItemInner::MetaItem(meta_item) = lint
24-
&& meta_item.is_word()
25-
&& let Some(ident) = meta_item.ident()
23+
let (namespace @ (Some(sym::clippy) | None), Some(name)) = namespace_and_lint(lint) else {
24+
return;
25+
};
26+
27+
if namespace.is_none()
2628
&& matches!(
27-
ident.name.as_str(),
29+
name.as_str(),
2830
"ambiguous_glob_reexports"
2931
| "dead_code"
3032
| "deprecated"
@@ -39,9 +41,9 @@ pub(super) fn check(cx: &EarlyContext<'_>, item: &Item, attrs: &[Attribute]) {
3941
return;
4042
}
4143

42-
if extract_clippy_lint(lint).is_some_and(|symbol| {
43-
matches!(
44-
symbol.as_str(),
44+
if namespace == Some(sym::clippy)
45+
&& matches!(
46+
name.as_str(),
4547
"wildcard_imports"
4648
| "enum_glob_use"
4749
| "redundant_pub_crate"
@@ -52,7 +54,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, item: &Item, attrs: &[Attribute]) {
5254
| "disallowed_types"
5355
| "unused_trait_names"
5456
)
55-
}) {
57+
{
5658
return;
5759
}
5860
},

clippy_lints/src/attrs/utils.rs

+13-8
Original file line numberDiff line numberDiff line change
@@ -75,13 +75,18 @@ fn is_relevant_expr(cx: &LateContext<'_>, typeck_results: &ty::TypeckResults<'_>
7575

7676
/// Returns the lint name if it is clippy lint.
7777
pub(super) fn extract_clippy_lint(lint: &MetaItemInner) -> Option<Symbol> {
78-
if let Some(meta_item) = lint.meta_item()
79-
&& meta_item.path.segments.len() > 1
80-
&& let tool_name = meta_item.path.segments[0].ident
81-
&& tool_name.name == sym::clippy
82-
{
83-
let lint_name = meta_item.path.segments.last().unwrap().ident.name;
84-
return Some(lint_name);
78+
match namespace_and_lint(lint) {
79+
(Some(sym::clippy), name) => name,
80+
_ => None,
81+
}
82+
}
83+
84+
/// Returns the lint namespace, if any, as well as the lint name. (`None`, `None`) means
85+
/// the lint had less than 1 or more than 2 segments.
86+
pub(super) fn namespace_and_lint(lint: &MetaItemInner) -> (Option<Symbol>, Option<Symbol>) {
87+
match lint.meta_item().map(|m| m.path.segments.as_slice()).unwrap_or_default() {
88+
[name] => (None, Some(name.ident.name)),
89+
[namespace, name] => (Some(namespace.ident.name), Some(name.ident.name)),
90+
_ => (None, None),
8591
}
86-
None
8792
}

tests/ui/useless_attribute.fixed

+9
Original file line numberDiff line numberDiff line change
@@ -134,3 +134,12 @@ pub mod ambiguous_glob_exports {
134134
pub use my_prelude::*;
135135
pub use my_type::*;
136136
}
137+
138+
// Regression test for https://github.com/rust-lang/rust-clippy/issues/13764
139+
pub mod unknown_namespace {
140+
pub mod some_module {
141+
pub struct SomeType;
142+
}
143+
#[allow(rustc::non_glob_import_of_type_ir_inherent)]
144+
use some_module::SomeType;
145+
}

tests/ui/useless_attribute.rs

+9
Original file line numberDiff line numberDiff line change
@@ -134,3 +134,12 @@ pub mod ambiguous_glob_exports {
134134
pub use my_prelude::*;
135135
pub use my_type::*;
136136
}
137+
138+
// Regression test for https://github.com/rust-lang/rust-clippy/issues/13764
139+
pub mod unknown_namespace {
140+
pub mod some_module {
141+
pub struct SomeType;
142+
}
143+
#[allow(rustc::non_glob_import_of_type_ir_inherent)]
144+
use some_module::SomeType;
145+
}

0 commit comments

Comments
 (0)