-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New lint: single_field_patterns
#8157
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
Conversation
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @flip1995 (or someone else) soon. Please see the contribution instructions for more information. |
This lint generates too many warnings to be warn by default. I tested it on around 1000 popular crates. I got 541 warnings. The 10 worst crates were:
Personally, I strongly prefer the pattern matching to the tuple indexing. I'd like to hear other people's opinions on this. From the implementation side, the only problem I found is that the suggestions don't handle macros correctly. #![allow(unused_variables)]
macro_rules! m {
() => { (1, 2, 30) }
}
fn main() {
let (_, x, _) = m!();
} outputs
|
I think you're in the majority (or there are enough people that prefer it that it should be opt-out). Breaking down 34 lints from
The frequency of plain tuple matching suggests that people are doing it intentionally. Also, of the struct lints, 5/6 were newtypes, which may also be something some people do intentionally.
Is there a pre-existing way to do that?
Would it make more sense if I made it configurable, and ignored plain tuples + newtypes by default? Depending on further tests on the 1000 crates.
Is there any way to make this do the expected thing, or should I just try to ignore code that has macros for either the pattern or scrutinee? |
clippy_lints/src/comparison_chain.rs
Outdated
} | ||
|
||
// Check that there exists at least one explicit else condition | ||
let (conds, _) = if_sequence(expr); | ||
let conds = if_sequence(expr).0; | ||
if conds.len() < 2 { | ||
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.
Hmm, my two cents;
I would not see this as an improvement in my own code. :/
If for example we do some code changes and it turns out we need the second return type of if_sequence()
as well, we'd have to revert back to (conds, ..)
which is more work than just replacing _
with a variable binding.
Considering the feedback, I've opted to only handle structs with named fields. I could add tuples/arrays/etc. back as a pedantic lint if anyone was interested, and assuming that's an appropriate category for them (they seem controversial). I don't think there's any getting around the loss of flexibility, but I think in some of these cases the decrease in verbosity is a fair trade-off. Here it seem reasonable to me - the type is no longer specified, and it's less verbose overall: -if let Spanned {
- node: LitKind::Bool(lit),
- ..
-} = *span
-{
+if let LitKind::Bool(lit) = span.node { Does that seem like a reasonable correction? Also, there are currently cases where it requires repetition, which isn't good - I'm planning on making changes to not lint these, but wanted to make sure I'm not wasting time with a bad design: -let Range { start, .. } = self.pixel_indices_unchecked(sx, sy);
+let start = self.pixel_indices_unchecked(sx, sy).start; |
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 for the way too late review, $day_job and christmas vacation got in the way..
This lint and its impl looks really good overall. I agree that tuples should not be linted.
Also, there are currently cases where it requires repetition, which isn't good - I'm planning on making changes to not lint these, but wanted to make sure I'm not wasting time with a bad design:
What do you mean by "repetition"?
No worries, I was also preoccupied with work and some other stuff for a while.
By repetition, I meant it would lint something like I've either replied to comments, or made the relevant changes - not sure if I should resolve conversations myself or wait for you to. Also, I'm not sure why CI is failing - my local machine is building/passing tests with rust 1.60.0 nightly, and the failing code doesn't seem problematic to me. Any ideas why that might be happening? |
You can resolve them yourself.
I would lint those too. If the user would care about the name, they would have named it in the
You probably need to rebase on the latest master. With that rebase you'll also get the same nightly that CI uses (the one specified in rust-toolchain.toml on the master branch) |
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 have one comment left. Not sure how hard it would be to implement this. If you can't find an easy way to do that, feel free to keep the current behavior. This can also be done in a future PR.
How to move forward:
Please rebase on top of the latest master. Also, please squash (some of) your commits. If you need help with that, let me know!
After that, I'll give it a final review and this should be ready to merge!
| | ||
help: try this | ||
| | ||
LL | let ref mut field1 = struct1.field1; |
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 think a better suggestion would be for the ref
and ref mut
pattern to borrow the field, instead of keeping it in the pattern. This is just more idiomatic Rust IMO.
@@ -0,0 +1,132 @@ | |||
#![warn(clippy::single_field_patterns)] |
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 be // run-rustfix
, since this lint is auto applicable in theory. With that comment on top of the test file, the UI tests will make sure that the suggestions are applied cleanly and don't break anything.
☔ The latest upstream changes (presumably #8575) made this pull request unmergeable. Please resolve the merge conflicts. |
Closing because of inactivity. @hahohihu if you want to continue to work on this, let me know! |
@flip1995 Sorry for abandoning this - life got in the way. Do you think I could pick it back up? |
changelog: Add
[`single_field_patterns`]
lintfixes #7122
Comments:
if let 1 = x[0]
to be suggested because handling it would require effectively re-implementing equatable_if_let, and it deals with the same issues. So I think dealing with that should be equatable_if_let's responsibility, and if people don't like it, they should enable that lint and do a second pass.