-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unused trait imports (formerly anonymous trait import) #13322
Conversation
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @y21 (or someone else) some time within the next two weeks. Please see the contribution instructions for more information. Namely, in order to ensure the minimum review times lag, PR authors and assigned reviewers should ensure that the review label (
|
I've not properly looked at the changes here in full detail but some initial comments:
I'd say that this is fine and even preferred (false negatives over false positives), especially for a lint that's going to be as trigger-heavy as this one. I wonder though, instead of reimplementing a part of resolution, could this use |
Thank you for the response. You are right. I had to change some of the tests but I think they are correct now and fixed the false negatives. |
Awesome lint, thanks!!! I would even suggest removing the You used Lastly, a tiny minor nit - you may want to move the |
20376b5
to
01856a3
Compare
Thanks @nyurik :) Yes I agree it shouldn't be wip anymore.
Yes, good point. The change to using
Ah that is a good point. I have moved main to the top. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A lot of the comments that I had before when I looked at this first are no longer relevant and fixed now with the extra visitor removed so that's nice :)
&& let module = cx.tcx.parent_module_from_def_id(item.owner_id.def_id) | ||
&& cx.tcx.visibility(item.owner_id.def_id) == Visibility::Restricted(module.to_def_id()) | ||
&& let Some(last_segment) = path.segments.last() | ||
&& let Some(snip) = snippet_opt(cx, last_segment.ident.span) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be good to have some macro checks to prevent cases where the lint is coming from an external macro.
For example the first 100 results here are almost all from within a bitflags!
macro expansion where the user can't change anything: https://github.com/rust-lang/rust-clippy/actions/runs/10657161173
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can use !in_external_macro(..)
&&
!is_from_proc_macro(..)
for that
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For some reason using is_from_proc_macro(cx, item)
wouldn't trigger when testing with with_span!
. I managed to get it working by using is_from_proc_macro(cx, &last_segment.ident)
but I don't understand why that worked and the former didn't.
FWIW, something like |
Thanks for the review.
Ah yes that is an interesting edge case. I have had a look at the HIR to see if it is easy to ignore this pattern but it seems to be hard to distinguish at that level.
I guess maybe I could use the span to check the source manually but that feels messy. If you are happy that it is not an issue that needs to be addressed then I am too :) |
☔ The latest upstream changes (presumably #13247) made this pull request unmergeable. Please resolve the merge conflicts. |
8d6272b
to
34db62c
Compare
☔ The latest upstream changes (presumably #12987) made this pull request unmergeable. Please resolve the merge conflicts. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me aside from a few small things
/// } | ||
/// ``` | ||
#[clippy::version = "1.82.0"] | ||
pub ANON_TRAIT_IMPORT, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pub ANON_TRAIT_IMPORT, | |
pub ANON_TRAIT_IMPORTS, |
Lint names should generally be in plural so it makes sense when read as "allow anon trait imports"
/// Traits imported that aren't used directly can be imported anonymously `use Trait as _`. | ||
/// It is more explicit, avoids polutting the current scope with unused names and can be useful to show which imports are required for traits. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// Traits imported that aren't used directly can be imported anonymously `use Trait as _`. | |
/// It is more explicit, avoids polutting the current scope with unused names and can be useful to show which imports are required for traits. | |
/// Traits imported that aren't used directly can be imported anonymously with `use Trait as _`. | |
/// It is more explicit, avoids polluting the current scope with unused names and can be useful to show which imports are required for traits. |
/// ``` | ||
#[clippy::version = "1.82.0"] | ||
pub ANON_TRAIT_IMPORT, | ||
nursery, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you intend to move this to a different category before the merge or keep it in the nursery for now?
Usually new lints start out in a more defined category. Nursery is typically for lints that are known to be buggy
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, I have moved it to pedantic.
This might be more or less tangential to this lint but we might also want to adjust rustc's suggestion for importing traits for methods. I imagine it would be somewhat annoying to apply the compiler's suggestion to import a trait only to immediately trigger a clippy lint. |
@y21 i agree, |
34db62c
to
c63465f
Compare
I have found another sub optimal scenario but don't think it is bad enough to prevent merge. It would be nice if multiple renames that import the same trait gets suggested to combine into a single import. Currently this produces a suggestion for each import meaning running use std::any::{Any, Any as MyAny}; After running use std::any::{Any as _, Any as _}; Rustc will lint one of the imports as unused so should highlight the issue. |
☔ The latest upstream changes (presumably #13369) made this pull request unmergeable. Please resolve the merge conflicts. |
I think that's fine. Or at least, I don't think this situation would be common enough to be an actual problem. It seems odd to import the same trait twice to begin with IMO. |
tests/ui/anon_trait_imports.rs
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please also add a test for making sure that #[allow(clippy::anon_trait_imports)]
on the use item works. You might have to include anon_trait_imports
here to avoid a false positive on the useless_attribute lint:
rust-clippy/clippy_lints/src/attrs/useless_attribute.rs
Lines 44 to 46 in 131681b
matches!( | |
symbol.as_str(), | |
"wildcard_imports" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's tests for #[allow]
on the enclosing module and function now, but not one for the use item directly as far as I can tell. I mean something like
#[allow(clippy::anon_trait_imports)]
use std::any::Any;
"".type_id();
Can you also add one for that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, added.
There is a false positive for useless_attribute
in this case
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Being able to allow the lint on the item that it warns on is something that should really work for all lints (without triggering other lints), so it would be good if you could fix that false positive for this lint. It should be fairly straightforward, you just need to add it to the matches!
macro (see initial comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, yeah I forgot that you explained how to fix that. Fixed 👍
c63465f
to
a287de0
Compare
Opened a thread on zulip for the FCP process that new lints need to go through: https://rust-lang.zulipchat.com/#narrow/stream/257328-clippy/topic/FCP.3A.20anon_trait_imports Implementation looks good to me aside from the test change that I commented on, but that shouldn't involve any major changes in a way that would block the FCP. |
Isn't this lint named backwards? Lints are named for what they report, not what they suggest you do instead, and this lint is objecting to unused names and suggesting an anonymous import. How about naming it |
Based on feedback in zulip I've renamed the lint from |
we could probably add it to |
yeah I agree but maybe it is best to do it in a follow up PR as it adds a lot of changes across clippy :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me now aside from two small things. Can you also squash the commits here a bit?
I also agree that if we're going to apply this style to the code base and enable the lint it should be done in a separate PR since it'll probably involve a discussion, which doesn't really need to block the lint itself
dfc5a52
to
739ef7b
Compare
I've addressed your review and squashed everything into two commits :) |
Great, thank you for implementing this lint! @bors r+ |
Unused trait imports (formerly anonymous trait import) For #11969 I'm looking for help and feedback on implementing a new lint for suggesting `use ... as _` for traits where possible. I have had a go at implementing this but I don't know if this is the best way to do it as I am new to clippy. There are some edge cases I can think of where this doesn't work but have aired on the side of false negatives instead of false positives. An example of a false negative. I couldn't figure out the best way to resolve an import from within clippy. The sub module imports MyAny so that cannot be anonymized but `use std::any::Any` could be. In this case it is not caught because `Any` and `MyAny` have the same DefId. ```rust mod nested_mod_used_bad1 { use std::any::Any; use std::any::Any as MyAny; mod foo { use crate::nested_mod_used_bad1::MyAny; fn foo() { println!("{:?}", MyAny::type_id("foo")); } } } ``` Any feedback is much appreciated.
💔 Test failed - checks-action_test |
PR description was missing a @bors retry |
☀️ Test successful - checks-action_dev_test, checks-action_remark_test, checks-action_test |
@y21 Great thank you for all your help, I'm glad we got this added! |
For #11969
I'm looking for help and feedback on implementing a new lint for suggesting
use ... as _
for traits where possible.I have had a go at implementing this but I don't know if this is the best way to do it as I am new to clippy.
There are some edge cases I can think of where this doesn't work but have aired on the side of false negatives instead of false positives.
An example of a false negative. I couldn't figure out the best way to resolve an import from within clippy. The sub module imports MyAny so that cannot be anonymized but
use std::any::Any
could be. In this case it is not caught becauseAny
andMyAny
have the same DefId.Any feedback is much appreciated.
changelog: new lint:
unused_trait_names