Skip to content

Commit 2642bb4

Browse files
committed
new lint: needless traits in scope
1 parent 41fa24c commit 2642bb4

7 files changed

+170
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4757,6 +4757,7 @@ Released 2018-09-13
47574757
[`needless_range_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_range_loop
47584758
[`needless_return`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_return
47594759
[`needless_splitn`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_splitn
4760+
[`needless_traits_in_scope`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_traits_in_scope
47604761
[`needless_update`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_update
47614762
[`neg_cmp_op_on_partial_ord`]: https://rust-lang.github.io/rust-clippy/master/index.html#neg_cmp_op_on_partial_ord
47624763
[`neg_multiply`]: https://rust-lang.github.io/rust-clippy/master/index.html#neg_multiply

clippy_lints/src/declared_lints.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
444444
crate::needless_parens_on_range_literals::NEEDLESS_PARENS_ON_RANGE_LITERALS_INFO,
445445
crate::needless_pass_by_value::NEEDLESS_PASS_BY_VALUE_INFO,
446446
crate::needless_question_mark::NEEDLESS_QUESTION_MARK_INFO,
447+
crate::needless_traits_in_scope::NEEDLESS_TRAITS_IN_SCOPE_INFO,
447448
crate::needless_update::NEEDLESS_UPDATE_INFO,
448449
crate::neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD_INFO,
449450
crate::neg_multiply::NEG_MULTIPLY_INFO,

clippy_lints/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ mod needless_late_init;
216216
mod needless_parens_on_range_literals;
217217
mod needless_pass_by_value;
218218
mod needless_question_mark;
219+
mod needless_traits_in_scope;
219220
mod needless_update;
220221
mod neg_cmp_op_on_partial_ord;
221222
mod neg_multiply;
@@ -926,6 +927,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
926927
});
927928
store.register_late_pass(|_| Box::new(no_mangle_with_rust_abi::NoMangleWithRustAbi));
928929
store.register_late_pass(|_| Box::new(collection_is_never_read::CollectionIsNeverRead));
930+
store.register_late_pass(|_| Box::new(needless_traits_in_scope::NeedlessTraitsInScope));
929931
// add lints here, do not remove this comment, it's used in `new_lint`
930932
}
931933

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
use clippy_utils::diagnostics::span_lint_and_sugg;
2+
use rustc_errors::Applicability;
3+
use rustc_hir::*;
4+
use rustc_lint::{LateContext, LateLintPass};
5+
use rustc_session::{declare_lint_pass, declare_tool_lint};
6+
7+
declare_clippy_lint! {
8+
/// ### What it does
9+
/// Find traits that are not explicitely used in scope (like `AsRef::as_ref()`)
10+
/// but directly with the trait method (like `opt.as_ref()`).
11+
///
12+
/// These traits can be imported anonymously with `use crate::Trait as _`.
13+
/// This avoids name collision with other traits (possibly with the same name).
14+
/// It also helps identify the traits in `use` statements.
15+
///
16+
/// ### Why is this bad?
17+
/// This needlessly brings a trait in trait's namespace.
18+
///
19+
/// ### Example
20+
/// ```rust
21+
/// use std::io::Read;
22+
/// fn main() {
23+
/// let mut b = "I'm your father!".as_bytes();
24+
/// let mut buffer = [0; 10];
25+
/// b.read(&mut buffer)
26+
/// }
27+
/// ```
28+
/// Use instead:
29+
/// ```rust
30+
/// use std::io::Read as _;
31+
/// fn main() {
32+
/// let mut b = "I'm your father!".as_bytes();
33+
/// let mut buffer = [0; 10];
34+
/// b.read(&mut buffer)
35+
/// }
36+
/// ```
37+
#[clippy::version = "1.69.0"]
38+
pub NEEDLESS_TRAITS_IN_SCOPE,
39+
pedantic,
40+
"trait is needlessly imported in trait's namespace, and can be anonymously imported"
41+
}
42+
declare_lint_pass!(NeedlessTraitsInScope => [NEEDLESS_TRAITS_IN_SCOPE]);
43+
44+
impl<'tcx> LateLintPass<'tcx> for NeedlessTraitsInScope {
45+
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
46+
// Only process `use` statements, ignore `UseKind::Glob`
47+
let ItemKind::Use(use_path, UseKind::Single) = item.kind else {
48+
return
49+
};
50+
// Check if the `use` is aliased with ` as `.
51+
// If aliased, then do not process, it's probably for a good reason
52+
if item.ident != use_path.segments.last().unwrap().ident {
53+
return;
54+
}
55+
let path = use_path
56+
.segments
57+
.iter()
58+
.map(|segment| segment.ident)
59+
.fold(String::new(), |mut acc, ident| {
60+
if !acc.is_empty() {
61+
acc += "::";
62+
}
63+
acc += ident.as_str();
64+
acc
65+
});
66+
span_lint_and_sugg(
67+
cx,
68+
NEEDLESS_TRAITS_IN_SCOPE,
69+
use_path.span,
70+
"trait is needlessly imported in trait's namespace",
71+
"you can import the trait anonymously",
72+
format!("{path} as _"),
73+
Applicability::MachineApplicable,
74+
);
75+
}
76+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// run-rustfix
2+
#![allow(unused)]
3+
#![warn(clippy::needless_traits_in_scope)]
4+
5+
pub mod useless_trait_in_scope {
6+
use std::io::Read as _;
7+
8+
pub fn warn() -> std::io::Result<usize> {
9+
let mut b = "The trait is not used explicitely -> 'use std::io::Read' doesn't need to be in scope".as_bytes();
10+
let mut buffer = [0; 10];
11+
b.read(&mut buffer)
12+
}
13+
}
14+
15+
pub mod trait_not_in_scope {
16+
use std::io::Read as _;
17+
18+
pub fn ok() -> std::io::Result<usize> {
19+
let mut b = "The trait is not used explicitely, but 'use std::io::Read' is already not in scope".as_bytes();
20+
let mut buffer = [0; 10];
21+
b.read(&mut buffer)
22+
}
23+
}
24+
25+
// FIXME: when the trait is explicitely used, the lint should not trigger
26+
// pub mod useful_trait_in_scope {
27+
// use std::io::Read;
28+
29+
// pub fn ok() -> std::io::Result<usize> {
30+
// let mut b = "Trait is used explicitely -> 'use std::io::Read' is OK".as_bytes();
31+
// let mut buffer = [0; 10];
32+
// Read::read(&mut b, &mut buffer)
33+
// }
34+
// }
35+
36+
fn main() {
37+
useless_trait_in_scope::warn();
38+
trait_not_in_scope::ok();
39+
// useful_trait_in_scope::ok();
40+
}

tests/ui/needless_traits_in_scope.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// run-rustfix
2+
#![allow(unused)]
3+
#![warn(clippy::needless_traits_in_scope)]
4+
5+
pub mod useless_trait_in_scope {
6+
use std::io::Read;
7+
8+
pub fn warn() -> std::io::Result<usize> {
9+
let mut b = "The trait is not used explicitely -> 'use std::io::Read' doesn't need to be in scope".as_bytes();
10+
let mut buffer = [0; 10];
11+
b.read(&mut buffer)
12+
}
13+
}
14+
15+
pub mod trait_not_in_scope {
16+
use std::io::Read as _;
17+
18+
pub fn ok() -> std::io::Result<usize> {
19+
let mut b = "The trait is not used explicitely, but 'use std::io::Read' is already not in scope".as_bytes();
20+
let mut buffer = [0; 10];
21+
b.read(&mut buffer)
22+
}
23+
}
24+
25+
// FIXME: when the trait is explicitely used, the lint should not trigger
26+
// pub mod useful_trait_in_scope {
27+
// use std::io::Read;
28+
29+
// pub fn ok() -> std::io::Result<usize> {
30+
// let mut b = "Trait is used explicitely -> 'use std::io::Read' is OK".as_bytes();
31+
// let mut buffer = [0; 10];
32+
// Read::read(&mut b, &mut buffer)
33+
// }
34+
// }
35+
36+
fn main() {
37+
useless_trait_in_scope::warn();
38+
trait_not_in_scope::ok();
39+
// useful_trait_in_scope::ok();
40+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error: trait is needlessly imported in trait's namespace
2+
--> $DIR/needless_traits_in_scope.rs:6:9
3+
|
4+
LL | use std::io::Read;
5+
| ^^^^^^^^^^^^^ help: you can import the trait anonymously: `std::io::Read as _`
6+
|
7+
= note: `-D clippy::needless-traits-in-scope` implied by `-D warnings`
8+
9+
error: aborting due to previous error
10+

0 commit comments

Comments
 (0)