Skip to content

Commit d445ced

Browse files
committed
Auto merge of rust-lang#9879 - Alexendoo:allow, r=Manishearth
Fix `#[allow]` for `module_name_repetitions` & `single_component_path_imports` Fixes rust-lang#7511 Fixes rust-lang#8768 Fixes rust-lang#9401 `single_component_path_imports` needed some changes to the lint itself, it now buffers the found single component paths to emit in the equivalent `check_item` changelog: Fix `#[allow(clippy::module_name_repetitions)]` and `#[allow(clippy::single_component_path_imports)]`
2 parents f60186f + 4d8af99 commit d445ced

8 files changed

+180
-120
lines changed

clippy_lints/src/attrs.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,9 @@ impl<'tcx> LateLintPass<'tcx> for Attributes {
378378
| "enum_glob_use"
379379
| "redundant_pub_crate"
380380
| "macro_use_imports"
381-
| "unsafe_removed_from_name",
381+
| "unsafe_removed_from_name"
382+
| "module_name_repetitions"
383+
| "single_component_path_imports"
382384
)
383385
})
384386
{

clippy_lints/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -792,7 +792,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
792792
store.register_late_pass(|_| Box::new(floating_point_arithmetic::FloatingPointArithmetic));
793793
store.register_early_pass(|| Box::new(as_conversions::AsConversions));
794794
store.register_late_pass(|_| Box::new(let_underscore::LetUnderscore));
795-
store.register_early_pass(|| Box::new(single_component_path_imports::SingleComponentPathImports));
795+
store.register_early_pass(|| Box::<single_component_path_imports::SingleComponentPathImports>::default());
796796
let max_fn_params_bools = conf.max_fn_params_bools;
797797
let max_struct_bools = conf.max_struct_bools;
798798
store.register_late_pass(move |_| {
Lines changed: 127 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg};
2+
use rustc_ast::node_id::{NodeId, NodeMap};
23
use rustc_ast::{ptr::P, Crate, Item, ItemKind, MacroDef, ModKind, UseTreeKind};
34
use rustc_errors::Applicability;
45
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
5-
use rustc_session::{declare_lint_pass, declare_tool_lint};
6+
use rustc_session::{declare_tool_lint, impl_lint_pass};
67
use rustc_span::{edition::Edition, symbol::kw, Span, Symbol};
78

89
declare_clippy_lint! {
@@ -33,51 +34,32 @@ declare_clippy_lint! {
3334
"imports with single component path are redundant"
3435
}
3536

36-
declare_lint_pass!(SingleComponentPathImports => [SINGLE_COMPONENT_PATH_IMPORTS]);
37+
#[derive(Default)]
38+
pub struct SingleComponentPathImports {
39+
/// Buffer found usages to emit when visiting that item so that `#[allow]` works as expected
40+
found: NodeMap<Vec<SingleUse>>,
41+
}
42+
43+
struct SingleUse {
44+
name: Symbol,
45+
span: Span,
46+
item_id: NodeId,
47+
can_suggest: bool,
48+
}
49+
50+
impl_lint_pass!(SingleComponentPathImports => [SINGLE_COMPONENT_PATH_IMPORTS]);
3751

3852
impl EarlyLintPass for SingleComponentPathImports {
3953
fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &Crate) {
4054
if cx.sess().opts.edition < Edition::Edition2018 {
4155
return;
4256
}
43-
check_mod(cx, &krate.items);
44-
}
45-
}
4657

47-
fn check_mod(cx: &EarlyContext<'_>, items: &[P<Item>]) {
48-
// keep track of imports reused with `self` keyword,
49-
// such as `self::crypto_hash` in the example below
50-
// ```rust,ignore
51-
// use self::crypto_hash::{Algorithm, Hasher};
52-
// ```
53-
let mut imports_reused_with_self = Vec::new();
54-
55-
// keep track of single use statements
56-
// such as `crypto_hash` in the example below
57-
// ```rust,ignore
58-
// use crypto_hash;
59-
// ```
60-
let mut single_use_usages = Vec::new();
61-
62-
// keep track of macros defined in the module as we don't want it to trigger on this (#7106)
63-
// ```rust,ignore
64-
// macro_rules! foo { () => {} };
65-
// pub(crate) use foo;
66-
// ```
67-
let mut macros = Vec::new();
68-
69-
for item in items {
70-
track_uses(
71-
cx,
72-
item,
73-
&mut imports_reused_with_self,
74-
&mut single_use_usages,
75-
&mut macros,
76-
);
58+
self.check_mod(cx, &krate.items);
7759
}
7860

79-
for (name, span, can_suggest) in single_use_usages {
80-
if !imports_reused_with_self.contains(&name) {
61+
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
62+
for SingleUse { span, can_suggest, .. } in self.found.remove(&item.id).into_iter().flatten() {
8163
if can_suggest {
8264
span_lint_and_sugg(
8365
cx,
@@ -102,74 +84,127 @@ fn check_mod(cx: &EarlyContext<'_>, items: &[P<Item>]) {
10284
}
10385
}
10486

105-
fn track_uses(
106-
cx: &EarlyContext<'_>,
107-
item: &Item,
108-
imports_reused_with_self: &mut Vec<Symbol>,
109-
single_use_usages: &mut Vec<(Symbol, Span, bool)>,
110-
macros: &mut Vec<Symbol>,
111-
) {
112-
if item.span.from_expansion() || item.vis.kind.is_pub() {
113-
return;
114-
}
87+
impl SingleComponentPathImports {
88+
fn check_mod(&mut self, cx: &EarlyContext<'_>, items: &[P<Item>]) {
89+
// keep track of imports reused with `self` keyword, such as `self::crypto_hash` in the example
90+
// below. Removing the `use crypto_hash;` would make this a compile error
91+
// ```
92+
// use crypto_hash;
93+
//
94+
// use self::crypto_hash::{Algorithm, Hasher};
95+
// ```
96+
let mut imports_reused_with_self = Vec::new();
11597

116-
match &item.kind {
117-
ItemKind::Mod(_, ModKind::Loaded(ref items, ..)) => {
118-
check_mod(cx, items);
119-
},
120-
ItemKind::MacroDef(MacroDef { macro_rules: true, .. }) => {
121-
macros.push(item.ident.name);
122-
},
123-
ItemKind::Use(use_tree) => {
124-
let segments = &use_tree.prefix.segments;
125-
126-
// keep track of `use some_module;` usages
127-
if segments.len() == 1 {
128-
if let UseTreeKind::Simple(None, _, _) = use_tree.kind {
129-
let name = segments[0].ident.name;
130-
if !macros.contains(&name) {
131-
single_use_usages.push((name, item.span, true));
132-
}
133-
}
134-
return;
98+
// keep track of single use statements such as `crypto_hash` in the example below
99+
// ```
100+
// use crypto_hash;
101+
// ```
102+
let mut single_use_usages = Vec::new();
103+
104+
// keep track of macros defined in the module as we don't want it to trigger on this (#7106)
105+
// ```
106+
// macro_rules! foo { () => {} };
107+
// pub(crate) use foo;
108+
// ```
109+
let mut macros = Vec::new();
110+
111+
for item in items {
112+
self.track_uses(
113+
cx,
114+
item,
115+
&mut imports_reused_with_self,
116+
&mut single_use_usages,
117+
&mut macros,
118+
);
119+
}
120+
121+
for usage in single_use_usages {
122+
if !imports_reused_with_self.contains(&usage.name) {
123+
self.found.entry(usage.item_id).or_default().push(usage);
135124
}
125+
}
126+
}
136127

137-
if segments.is_empty() {
138-
// keep track of `use {some_module, some_other_module};` usages
139-
if let UseTreeKind::Nested(trees) = &use_tree.kind {
140-
for tree in trees {
141-
let segments = &tree.0.prefix.segments;
142-
if segments.len() == 1 {
143-
if let UseTreeKind::Simple(None, _, _) = tree.0.kind {
144-
let name = segments[0].ident.name;
145-
if !macros.contains(&name) {
146-
single_use_usages.push((name, tree.0.span, false));
147-
}
148-
}
128+
fn track_uses(
129+
&mut self,
130+
cx: &EarlyContext<'_>,
131+
item: &Item,
132+
imports_reused_with_self: &mut Vec<Symbol>,
133+
single_use_usages: &mut Vec<SingleUse>,
134+
macros: &mut Vec<Symbol>,
135+
) {
136+
if item.span.from_expansion() || item.vis.kind.is_pub() {
137+
return;
138+
}
139+
140+
match &item.kind {
141+
ItemKind::Mod(_, ModKind::Loaded(ref items, ..)) => {
142+
self.check_mod(cx, items);
143+
},
144+
ItemKind::MacroDef(MacroDef { macro_rules: true, .. }) => {
145+
macros.push(item.ident.name);
146+
},
147+
ItemKind::Use(use_tree) => {
148+
let segments = &use_tree.prefix.segments;
149+
150+
// keep track of `use some_module;` usages
151+
if segments.len() == 1 {
152+
if let UseTreeKind::Simple(None, _, _) = use_tree.kind {
153+
let name = segments[0].ident.name;
154+
if !macros.contains(&name) {
155+
single_use_usages.push(SingleUse {
156+
name,
157+
span: item.span,
158+
item_id: item.id,
159+
can_suggest: true,
160+
});
149161
}
150162
}
163+
return;
151164
}
152-
} else {
153-
// keep track of `use self::some_module` usages
154-
if segments[0].ident.name == kw::SelfLower {
155-
// simple case such as `use self::module::SomeStruct`
156-
if segments.len() > 1 {
157-
imports_reused_with_self.push(segments[1].ident.name);
158-
return;
159-
}
160165

161-
// nested case such as `use self::{module1::Struct1, module2::Struct2}`
166+
if segments.is_empty() {
167+
// keep track of `use {some_module, some_other_module};` usages
162168
if let UseTreeKind::Nested(trees) = &use_tree.kind {
163169
for tree in trees {
164170
let segments = &tree.0.prefix.segments;
165-
if !segments.is_empty() {
166-
imports_reused_with_self.push(segments[0].ident.name);
171+
if segments.len() == 1 {
172+
if let UseTreeKind::Simple(None, _, _) = tree.0.kind {
173+
let name = segments[0].ident.name;
174+
if !macros.contains(&name) {
175+
single_use_usages.push(SingleUse {
176+
name,
177+
span: tree.0.span,
178+
item_id: item.id,
179+
can_suggest: false,
180+
});
181+
}
182+
}
183+
}
184+
}
185+
}
186+
} else {
187+
// keep track of `use self::some_module` usages
188+
if segments[0].ident.name == kw::SelfLower {
189+
// simple case such as `use self::module::SomeStruct`
190+
if segments.len() > 1 {
191+
imports_reused_with_self.push(segments[1].ident.name);
192+
return;
193+
}
194+
195+
// nested case such as `use self::{module1::Struct1, module2::Struct2}`
196+
if let UseTreeKind::Nested(trees) = &use_tree.kind {
197+
for tree in trees {
198+
let segments = &tree.0.prefix.segments;
199+
if !segments.is_empty() {
200+
imports_reused_with_self.push(segments[0].ident.name);
201+
}
167202
}
168203
}
169204
}
170205
}
171-
}
172-
},
173-
_ => {},
206+
},
207+
_ => {},
208+
}
174209
}
175210
}
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
error: this import is redundant
2-
--> $DIR/single_component_path_imports.rs:23:5
2+
--> $DIR/single_component_path_imports.rs:5:1
33
|
4-
LL | use regex;
5-
| ^^^^^^^^^^ help: remove it entirely
4+
LL | use regex;
5+
| ^^^^^^^^^^ help: remove it entirely
66
|
77
= note: `-D clippy::single-component-path-imports` implied by `-D warnings`
88

99
error: this import is redundant
10-
--> $DIR/single_component_path_imports.rs:5:1
10+
--> $DIR/single_component_path_imports.rs:23:5
1111
|
12-
LL | use regex;
13-
| ^^^^^^^^^^ help: remove it entirely
12+
LL | use regex;
13+
| ^^^^^^^^^^ help: remove it entirely
1414

1515
error: aborting due to 2 previous errors
1616

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
1+
error: this import is redundant
2+
--> $DIR/single_component_path_imports_nested_first.rs:4:1
3+
|
4+
LL | use regex;
5+
| ^^^^^^^^^^ help: remove it entirely
6+
|
7+
= note: `-D clippy::single-component-path-imports` implied by `-D warnings`
8+
19
error: this import is redundant
210
--> $DIR/single_component_path_imports_nested_first.rs:13:10
311
|
412
LL | use {regex, serde};
513
| ^^^^^
614
|
715
= help: remove this import
8-
= note: `-D clippy::single-component-path-imports` implied by `-D warnings`
916

1017
error: this import is redundant
1118
--> $DIR/single_component_path_imports_nested_first.rs:13:17
@@ -15,11 +22,5 @@ LL | use {regex, serde};
1522
|
1623
= help: remove this import
1724

18-
error: this import is redundant
19-
--> $DIR/single_component_path_imports_nested_first.rs:4:1
20-
|
21-
LL | use regex;
22-
| ^^^^^^^^^^ help: remove it entirely
23-
2425
error: aborting due to 3 previous errors
2526

tests/ui/useless_attribute.fixed

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// run-rustfix
22
// aux-build:proc_macro_derive.rs
33

4+
#![allow(unused)]
45
#![warn(clippy::useless_attribute)]
56
#![warn(unreachable_pub)]
67
#![feature(rustc_private)]
@@ -16,6 +17,13 @@ extern crate rustc_middle;
1617
#[macro_use]
1718
extern crate proc_macro_derive;
1819

20+
fn test_indented_attr() {
21+
#![allow(clippy::almost_swapped)]
22+
use std::collections::HashSet;
23+
24+
let _ = HashSet::<u32>::default();
25+
}
26+
1927
// don't lint on unused_import for `use` items
2028
#[allow(unused_imports)]
2129
use std::collections;
@@ -63,13 +71,16 @@ mod c {
6371
pub(crate) struct S;
6472
}
6573

66-
fn test_indented_attr() {
67-
#![allow(clippy::almost_swapped)]
68-
use std::collections::HashSet;
69-
70-
let _ = HashSet::<u32>::default();
74+
// https://github.com/rust-lang/rust-clippy/issues/7511
75+
pub mod split {
76+
#[allow(clippy::module_name_repetitions)]
77+
pub use regex::SplitN;
7178
}
7279

80+
// https://github.com/rust-lang/rust-clippy/issues/8768
81+
#[allow(clippy::single_component_path_imports)]
82+
use regex;
83+
7384
fn main() {
7485
test_indented_attr();
7586
}

0 commit comments

Comments
 (0)