-
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
New lint missing_iterator_fold
#12211
New lint missing_iterator_fold
#12211
Conversation
`cargo dev new_lint --name=missing_iterator_fold --pass=late`
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @blyxyas (or someone else) soon. 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 (
|
a77a1b0
to
84b52f8
Compare
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.
Very good first iteration! Thanks for the contribution, I have some small questions and nits, but this is a very good state.
|
||
impl LateLintPass<'_> for MissingIteratorFold { | ||
fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { | ||
if rustc_middle::lint::in_external_macro(cx.sess(), item.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.
We generally import this function
.map(|assoc| assoc.ident.name.as_str()) | ||
.any(|name| name == "fold"); |
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.
This map can be removed to avoid walking over the iterator (and allocating memory) more than necessary
.map(|assoc| assoc.ident.name.as_str()) | |
.any(|name| name == "fold"); | |
.any(|assoc| assoc.ident.name.as_str() == "fold"); |
/// ``` | ||
#[clippy::version = "1.77.0"] | ||
pub MISSING_ITERATOR_FOLD, | ||
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.
Hmmmm... what category do you think that this should be? I'm thinking about perf
, but the lint may be too demanding to be put in perf
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.
This is definitely about perf
ormance but there is also pedantic
because this is "rather strict".
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.
Is this actually actionable in all cases? As in, can you always provide a more useful implementation than the default fold
implementation? Because if not, I'd go as far as saying it could be a restriction
lint. For example, std's Range
Iterator
implementation also does not implement fold
and I'm not sure how/why it should
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.
I don't see a reason why specialize fold
would necessarily improve performance in the general case. It certainly is in some cases but not all.
This is definitely a lint that should be allowed in some cases after some consideration (and benchmark). This is exactly our case at rust-itertools.
Not sure why either about Range
(while RangeInclusive
does if I remember well).
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.
I updated the category to restriction
.
tests/ui/missing_iterator_fold.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.
Just for the sake of completion, could you add another struct but implement fold
, just to make sure that it doesn't lint then?
@blyxyas Hi! Each point was addressed. Is there anything else or should I just squash my commits? (and rebase?) Should I suggest a blank |
I don't think so, that would prompt users to just leave it unchanged.
Hmmmm... These should be the same lint imo. Creating 3 - 4 lints just for slightly different methods would be... Also, do you have an example where manually implementing |
rust-itertools/itertools#775 had benchmarks 34 times faster but that's the exception. Most other Have a single lint for However, I clearly understand that you don't want a bunch of lints.
Leading to a total of three lints (in a same lint pass). Most I think that specialize those are good practices and can have huge impact on the EDIT: Maybe merge EDIT 2: |
Before this PR, I took advice on zulip and the discussion here eventually took place back on zulip. |
fixes #12209
Specialize
fold
might improve performance of methods relying on it and other iterator adaptors callingfold
.changelog: [
missing_iterator_fold
]: Check thatIterator
implementations specialize thefold
method.I am still questioning myself about the lint name, is "missing" appropriate?
I am unsure if
in_external_macro
check is needed or not in this situation.Note: I would (later) suggest similar lints for
DoubleEndedIterator::rfold
(andIterator::try_fold
/DoubleEndedIterator::try_rfold
except they currently can't be specialized on Rust stable since the traitTry
is still unstable) andIterator::size_hint
. All those lints could solved with a singleLateLintPass
.