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

lint matchable if let for pattern #9221

Closed
dswij opened this issue Jul 21, 2022 · 13 comments · Fixed by #9368
Closed

lint matchable if let for pattern #9221

dswij opened this issue Jul 21, 2022 · 13 comments · Fixed by #9368
Assignees
Labels
A-lint Area: New lints C-enhancement Category: Enhancement of lints, like adding more cases or adding help messages good-first-issue These issues are a good way to get started with Clippy

Comments

@dswij
Copy link
Member

dswij commented Jul 21, 2022

What it does

Checks for if let for patterns that can be re-written with matches!

This can be an improvement to equatable_if_let lint.

For background see #9102 (comment)

Lint Name

No response

Category

No response

Advantage

Similar to equatable_if_let:

  1. It reads better and has less cognitive load because equality won’t cause binding.
  2. It avoids a Yoda condition.
  3. Equality is a simple bool expression and can be merged with && and || and reuse if blocks

Drawbacks

No response

Example

#![allow(dead_code)]
enum Foo {
    Bar,
    Baz,
}

fn test(foo: Foo) {
    if let Foo::Baz = foo {
        println!("Foo::Baz");
    }
}

can be written as

#![allow(dead_code)]
enum Foo {
    Bar,
    Baz,
}

fn test(foo: Foo) {
    if matches!(foo, Foo::Baz) {
        println!("Foo::Baz");
    }
}
@dswij dswij added C-enhancement Category: Enhancement of lints, like adding more cases or adding help messages A-lint Area: New lints labels Jul 21, 2022
@dswij
Copy link
Member Author

dswij commented Jul 21, 2022

We can use equatable_if_let as a starting point, this should be a good first issue

@dswij dswij added the good-first-issue These issues are a good way to get started with Clippy label Jul 21, 2022
@dswij dswij changed the title lint equatable if let for pattern lint matchable if let for pattern Jul 21, 2022
@dswij
Copy link
Member Author

dswij commented Aug 1, 2022

Also, the logic would also be similar to match_like_matches_macro.

@nahuakang
Copy link
Contributor

@rustbot claim

@nahuakang
Copy link
Contributor

@dswij 👋 May I ask if you meant that we should add the new linting within equatable_if_let, i.e. expanding the logic of the existing equatable_if_let lint to include this new pattern? Thanks :)

@dswij
Copy link
Member Author

dswij commented Aug 21, 2022

I haven't taken a deep look into it, but if we plan to add this to a new lint, we can factor out reusable logic from equatable_if_let. Alternatively, we can just add this case to be linted by equatable_if_let and update the lint's docs.

@nahuakang
Copy link
Contributor

Thanks. I'll take a deeper look at the 2 lints that you've written down and circle back when I have a clearer picture :)

@nahuakang
Copy link
Contributor

@dswij It seems that equatable_if_let already takes care of the case you mentioned (I wonder if dogfood would have caught it). In this case, do we prefer: if foo == Foo::Baz or if matches!(foo, Foo::Baz)?

@dswij
Copy link
Member Author

dswij commented Aug 23, 2022

@nahuakang

it seems like it won't fire if PartialEq is not implemented. See (playground). The test cases for this lint seems to agree.

Makes sense since if PartialEq is not implemented, then you can't suggest if foo == Foo::Baz

So I think this is more of an improvement - if it doesn't implement PartialEq, then we can suggest using matches instead.

@nahuakang
Copy link
Contributor

@dswij Thanks for the tip. I was trying to understand this lint but had some trouble yesterday. Does your suggestion mean that if is_structural_partial_eq returns false, we could consider suggesting matches?

@dswij
Copy link
Member Author

dswij commented Aug 23, 2022

Yes, exactly. Suggest matches if it doesn't implement PartialEq.

I'm trying to think of scenarios where suggesting matches would be wrong, but I'm having trouble coming up with one. Just something to keep in mind.

@nahuakang
Copy link
Contributor

Will do! I'll start adding some new test cases and do the improvement. Maybe by the time of review we'd think of more edge cases.

@nahuakang
Copy link
Contributor

@dswij Feel free to take a look at the PR :) I'm still not familiar with things on this level so might miss some edge cases.

@bors bors closed this as completed in 628a79d Oct 23, 2022
@ivan-aksamentov
Copy link

ivan-aksamentov commented Feb 18, 2023

@nahuakang Excuse me if this is a wrong place to ask, but after this change to the equatable_if_let, it suggests turning conditions like

if let (None, None) = (&self.x, &self.y) {

into

if matches!((&self.x, &self.y), (None, None)) {

which I would consider worse.

Otherwise equatable_if_let is a fantastic, helpful lint, but I think this matches!() addition is bolted into a wrong place. Is it not too late to extract the matches!() part of it into a separate lint (which I would disable) and to roll back the previous version of the equatable_if_let, which only suggests things like ==?

How do I properly request a feature or open a discussion for this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-lint Area: New lints C-enhancement Category: Enhancement of lints, like adding more cases or adding help messages good-first-issue These issues are a good way to get started with Clippy
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants