-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Add lint to suggest as_chunks over chunks_exact with constant #16002
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
base: master
Are you sure you want to change the base?
Add lint to suggest as_chunks over chunks_exact with constant #16002
Conversation
This comment has been minimized.
This comment has been minimized.
|
Lintcheck changes for 2731771
This comment will be updated if you push new changes |
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 start:) Left a couple suggestions
| LL | let mut it = slice.chunks_exact(CHUNK_SIZE); | ||
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
| | | ||
| = help: consider using `as_chunks::<4>()` for better ergonomics |
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.
As this example shows, the suggestion replace even named constants with their values. To fix that, build the suggestion using a snippet of arg, to preserve its textual representation:
- format!("consider using `{suggestion}::<{chunk_size}>()` for better ergonomics")
+ let arg_str = snippet(cx, arg.span, "_");
+ format!("consider using `{suggestion}::<{arg_str}>()` for better ergonomics")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.
Done in 610acda
|
|
||
| // Should trigger lint - literal constant | ||
| let mut it = slice.chunks_exact(4); | ||
| //~^ ERROR: using `chunks_exact` with a constant chunk size |
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: you could also use the lint name, which is a bit shorter:
| //~^ ERROR: using `chunks_exact` with a constant chunk size | |
| //~^ chunks_exact_to_as_chunks |
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.
Done in 610acda
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.
Oh, no, that's not what I meant.. sorry for not articulating myself clearly.
The error message by itself is great, no need to change it. It's just that in the ui-test file, you can specify the error annotation not only as //~^ ERROR: <error message>, but also as //~^ <lint_name> (in your case, //~^ chunks_exact_with_const_size, which makes the test suite much less verbose overall, and so that's the change I was proposing.
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 guess I misunderstood, and I hope this hash is correctly implemented and suits your suggestion bc1d010.
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.
Yes, that's exactly what I meant:)
clippy_lints/src/methods/mod.rs
Outdated
| /// for chunk in chunks {} | ||
| /// ``` | ||
| #[clippy::version = "1.93.0"] | ||
| pub CHUNKS_EXACT_TO_AS_CHUNKS, |
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.
lint names usually either point out the "bad" pattern used (e.g. ok_expect), or what the pattern could be replaced with (e.g. manual_map). I think yours could use the former scheme, and be called something like chunks_exact_with_const_size
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.
Done in 610acda
| "as_chunks" | ||
| }; | ||
|
|
||
| span_lint_and_help( |
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 could be pretty effortlessly switched over to give suggestions, which are quite nice to have. https://doc.rust-lang.org/clippy/development/emitting_lints.html#suggestions-automatic-fixes should help you in that, but don't hesitate to ask if something's unclear
| // Check receiver is slice or array type | ||
| let recv_ty = cx.typeck_results().expr_ty(recv).peel_refs(); | ||
| if !recv_ty.is_slice() && !recv_ty.is_array() { | ||
| return; | ||
| } |
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.
You want to check for types that can be adjusted to slices, which includes e.g. Vec. For that, you can use TyCtxt::expr_ty_adjusted:
| // Check receiver is slice or array type | |
| let recv_ty = cx.typeck_results().expr_ty(recv).peel_refs(); | |
| if !recv_ty.is_slice() && !recv_ty.is_array() { | |
| return; | |
| } | |
| // Check if receiver is slice-like | |
| if !cx.typeck_results().expr_ty_adjusted(recv).peel_refs().is_slice() { | |
| return; | |
| } |
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.
Done in 1d99b91
| // Check for Rust version | ||
| if !msrv.meets(cx, msrvs::AS_CHUNKS) { | ||
| return; | ||
| } |
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 check is somewhat expensive, so it's best to perform it towards the end, e.g. after the constant check
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.
Done in 2731771
Suggest using slice.as_chunks::<N>() when chunks_exact(N) is called with a compile-time constant. This provides better ergonomics and type safety. Fixes rust-lang#15882
Changed example suggestion from const to snippet Shortend error message Followed clippy naming conventions
849dbe8 to
610acda
Compare
|
This PR was rebased onto a different master commit. Here's a range-diff highlighting what actually changed. Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers. |
|
| ); | ||
| }, | ||
| (name @ (sym::chunks_exact | sym::chunks_exact_mut), [arg]) => { | ||
| chunks_exact_with_const_size::check(cx, expr, recv, arg, name, self.msrv); |
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.
Currently, the span that the lint points at is the whole method call expression (expr.span) -- as the last result in Lintcheck (https://github.com/rust-lang/rust-clippy/actions/runs/19080004877#user-content-chunks-exact-with-const-size) shows, that might lead to a somewhat confusing diagnostics:
warning: chunks_exact_with_const_size
--> target/lintcheck/sources/rustc-demangle-0.1.24/src/v0.rs:299:25
|
299 | let mut bytes = self
| _________________________^
300 | | .nibbles
301 | | .as_bytes()
302 | | .chunks_exact(2)
| |____________________________^
|
= help: consider using `as_chunks::<2>()` for better ergonomics
= note: `--force-warn clippy::chunks-exact-with-const-size` implied by `--force-warn clippy::all`
You can instead only highlight the method call (in this case, chunks_exact(2), by using call_span, which comes from the call to method_call(expr) above (line 13) -- see filter_map_bool_then for a (somewhat) simple example
Adds a new lint
chunks_exact_to_as_chunksthat suggests usingas_chunksinstead ofchunks_exactwhen the chunk size is a compile-time constant.changelog: [
chunks_exact_to_as_chunks]: Suggest using slice.as_chunks::() when chunks_exact(N) is called with a compile-time constant. This provides better ergonomics and type safety.fixes #15882