-
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
add a new lint for repeat().take()
that can be replaced with repeat_n()
#13858
base: master
Are you sure you want to change the base?
Conversation
55203fc
to
33a5b21
Compare
clippy_utils/src/lib.rs
Outdated
@@ -15,6 +15,7 @@ | |||
clippy::missing_errors_doc, | |||
clippy::missing_panics_doc, | |||
clippy::must_use_candidate, | |||
clippy::redundant_repeat_take, |
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’m unsure whether I should add an allow rule like this, or if I should fix the part of the code that triggers the linting error, since currently there is only one part that is affected by this lint...
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 lint looks useful to have to me so I think keeping it enabled is a good idea. The case also looks like it should be fairly easy to fix
clippy_lints/src/methods/mod.rs
Outdated
/// | ||
/// ### Why is this bad? | ||
/// | ||
/// Using `repeat_n()` is more concise and clearer. |
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.
May also be worth pointing out that it can be faster for types that are non-trivial to clone as it knows the repeat count and only needs to clone n-1 times
clippy_utils/src/lib.rs
Outdated
@@ -15,6 +15,7 @@ | |||
clippy::missing_errors_doc, | |||
clippy::missing_panics_doc, | |||
clippy::must_use_candidate, | |||
clippy::redundant_repeat_take, |
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 lint looks useful to have to me so I think keeping it enabled is a good idea. The case also looks like it should be fairly easy to fix
&& let QPath::Resolved(_, path) = qpath | ||
&& path.segments.len() == 1 | ||
&& path.segments[0].ident.name.as_str() == "repeat" | ||
{ |
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 should have an MSRV check as repeat_n was only very recently stabilized
&& let ExprKind::Call(inner, repeat_args) = repeat_expr.kind | ||
&& repeat_args.len() == 1 |
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.
nit:
&& let ExprKind::Call(inner, repeat_args) = repeat_expr.kind | |
&& repeat_args.len() == 1 | |
&& let ExprKind::Call(inner, [repeat_arg]) = repeat_expr.kind |
&& let ExprKind::Path(ref qpath) = inner.kind | ||
&& let QPath::Resolved(_, path) = qpath | ||
&& path.segments.len() == 1 | ||
&& path.segments[0].ident.name.as_str() == "repeat" |
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.
iter::repeat
is a diagnostic item, so you should be able to match against its DefId
rather than looking for exact paths. Something like
&& let Some(def_id) = fn_def_id(inner)
&& cx.tcx.is_diagnostic_item(sym::iter_repeat, def_id)
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 should also be a check that the .take()
call is the take
from the Iterator trait and not from a user defined trait, with is_trait_method(cx, expr, sym::Iterator)
tests/ui/manual_str_repeat.rs
Outdated
@@ -1,4 +1,4 @@ | |||
#![allow(non_local_definitions)] | |||
#![allow(non_local_definitions, redundant_repeat_take)] |
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.
Should be clippy::redundant_repeat_take
. The test file also has errors because of that
snippet(cx, repeat_args[0].span, ""), | ||
snippet(cx, take_arg.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 a test case where the element is a macro call, e.g. repeat(vec![1, 2]).take(2)
. I suspect this currently "doesn't work" (has macro expansion in the suggestion), so this may need to use snippet_with_context
(with expr.span.ctxt()
for the ctxt), but I have not tested it
snippet(cx, repeat_args[0].span, ""), | ||
snippet(cx, take_arg.span, "") | ||
), | ||
Applicability::MachineApplicable, |
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.
FWIW, this changes the expression's type so it can lead to compile errors in some cases where its type is unified with other branches, e.g.:
// From an external library the user doesn't get to control
mod external_lib {
pub fn iter() -> std::iter::Take<std::iter::Repeat<&'static [u8]>> { todo!() }
}
let iter = match 1 {
1 => external_lib::iter(),
2 => std::iter::repeat([1,2].as_slice()).take(2) // can't really change this to repeat_n
};
so in those situations MachineApplicable
could lead to issues. There have been a few false positive reports of the like in the past (#11761 comes to mind).
Adding !expr_use_ctxt(cx, expr).is_ty_unified
to the chain could help avoid this I think. (edited, was thinking of the wrong util function before)
f3ac7b1
to
8e422ea
Compare
repeat().take()
repeat().take()
that can be replaced with repeat_n()
8e422ea
to
4bcd4a5
Compare
4bcd4a5
to
87082a2
Compare
546bbf1
to
672d7c0
Compare
@y21 Thank you for your thorough review! Looks like I was able to fix the reviewed items. Could you please take a look again? |
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 noticed this lint should suggest to use core::iter::repeat_n
in a no_std
environment. Therefore, I'll make a change.
close #13271
changelog: [
redundant_repeat_take
]: new lint