Skip to content
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

Fixing a false positive for the match_single_binding lint #5552 #6435

Merged

Conversation

xFrednet
Copy link
Member

@xFrednet xFrednet commented Dec 9, 2020

This is a fix for a false positive in the match_single_binding lint when using #[cfg()] on a branch. It is sadly a bit hacky but maybe the best solution as rust removes the other branch from the AST before we can even validate it. This fix looks at the code snippet itself and returns if it includes another thick arrow => besides the one matching arm we found. This can again cause false negatives if someone has the following code:

match x {
    // => <-- Causes a false negative
    _ => 1,
}

I thought about making the code more complex and maybe validating against other things like the #[cfg()] macro but I believe that this is the best solution. This has basically switched the issue from a false positive to a false negative in a very specific case.

I'm happy to make some changes if you have any suggestions 🙃.


Fixes #5552

changelog: Fixed a false positive in the match_single_binding lint with #[cfg()] macro

@rust-highfive
Copy link

r? @ebroto

(rust-highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties label Dec 9, 2020
@camsteffen
Copy link
Contributor

I think a proper fix here would involve register_pre_expansion_pass to inspect arms before cfg expansion. But I think it would be the first time a lint has both pre-expansion and post-expansion passes so that would require some high-level changes.

@xFrednet
Copy link
Member Author

That sounds like a nice way of doing that. Should I try to solve it like you suggested @camsteffen or should this first be discusses further? 🤔

@camsteffen
Copy link
Contributor

I think a maintainer needs to weigh in. I'm just some random guy.

@xFrednet
Copy link
Member Author

It is still very helpful, thank you 🙃. I thought about implementing it by first keeping track of all the arms and your comment goves a good starting point with register_pre_expansion_pass. I'll wait on a maintainer comment until I restructure the code.

@xFrednet
Copy link
Member Author

@camsteffen I've read through your comment again and I'm not 100% sure that I understand you correctly 😅.

I think it would be the first time a lint has both pre-expansion and post-expansion

Do you mean that we register a pre-expansion and post-expansion lint pass for the same lint or for the same struct?

The lint it self can be checked in the EarlyLintPass all together, I believe. It is also ignorant of the other lint checks so it should probably be pretty strait forward to create a new struct that impls EarlyLintPass for this lint. (Current lint check call)

Copy link
Member

@ebroto ebroto left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your contribution @xFrednet, and @camsteffen for your review.

Unfortunately, since #5518 we're actively avoiding adding new pre-expansion passes for the reasons stated there. TL;DR it's not clear they will be supported in the future in rustc. Pre-expansion passes are also quite problematic since you miss a lot of code. In this particular case, we're explicitly avoiding macros, so it would work, but otherwise this same construct would not be detected if it was generated during expansion.

I think this is a problem that could affect almost any lint. The inability to use pre-expansion passes is also a recurring problem. IMO the best approach here would be to find a general solution, probably implemented directly in rustc. Right now I'm not sure what would be the best approach, so I'm going to take note of this and think about opening a more general issue.

For the moment I'm inclined to accept this patch, but understanding that this should not set a precedent.

Comment on lines 1243 to 1245
if let Some(match_snippet) = snippet_opt(cx, expr.span) {
if let Some(arm_snippet) = snippet_opt(cx, arms[0].span) {
if let Some(ex_snippet) = snippet_opt(cx, ex.span) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could use an if_chain here to reduce the right-ward drift.

Comment on lines 1241 to 1242
// Check that the match doesn't contain other branches that might be excluded by `#[cfg]` or other
// macros
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should state more clearly in the comment that this is a HACK: and that we can't do better currently.

@ebroto ebroto added S-waiting-on-author Status: This is awaiting some action from the author. (Use `@rustbot ready` to update this status) and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties labels Dec 12, 2020
@xFrednet xFrednet force-pushed the 5552-false-positive-match-single-binding branch from 07d1d8d to 5997146 Compare December 12, 2020 21:10
@xFrednet xFrednet requested a review from ebroto December 12, 2020 21:19
@xFrednet
Copy link
Member Author

I've implemented your suggestions and rebased on master.

I agree that there should be a general non hacky way to do this. It would be awesome if you would share the issue if you decide to create one. Thank you for the work and the review @ebroto! 🙃

Copy link
Member

@ebroto ebroto left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks!

Could you squash before we merge? There are some intermediary commits.


It would be awesome if you would share the issue if you decide to create one

I hope this gets into the roadmap for 2021 because it's been a recurrent problem for the past months. I will be glad to share the issue if you would like to help!

* Applying suggested changes from the PR
@xFrednet xFrednet force-pushed the 5552-false-positive-match-single-binding branch from 5997146 to a37af06 Compare December 13, 2020 21:04
@xFrednet
Copy link
Member Author

Jup, they are squashed.


I would like to help! However, I'm a bit unsure if I have the sufficient knowledge to be a good support.

@ebroto
Copy link
Member

ebroto commented Dec 13, 2020

@bors r+


I would like to help! However, I'm a bit unsure if I have the sufficient knowledge to be a good support.

Any kind of help is welcome! I'll make sure to ping you after this has been discussed and we have a plan. Thanks for your willingness to help!

@bors
Copy link
Collaborator

bors commented Dec 13, 2020

📌 Commit a37af06 has been approved by ebroto

@bors
Copy link
Collaborator

bors commented Dec 13, 2020

⌛ Testing commit a37af06 with merge d924164...

@bors
Copy link
Collaborator

bors commented Dec 13, 2020

☀️ Test successful - checks-action_dev_test, checks-action_remark_test, checks-action_test
Approved by: ebroto
Pushing d924164 to master...

@bors bors merged commit d924164 into rust-lang:master Dec 13, 2020
@xFrednet xFrednet deleted the 5552-false-positive-match-single-binding branch July 28, 2021 16:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-author Status: This is awaiting some action from the author. (Use `@rustbot ready` to update this status)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

match_single_binding: false positive with #[cfg]
5 participants