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

match with default branch that would better be let-else. #12793

Closed
ltratt opened this issue May 13, 2024 · 3 comments
Closed

match with default branch that would better be let-else. #12793

ltratt opened this issue May 13, 2024 · 3 comments
Labels
A-lint Area: New lints

Comments

@ltratt
Copy link

ltratt commented May 13, 2024

What it does

I'm working on a moderately old codebase that has a number of instances of this idiom:

let z = match x {
  Y(z) => z,
  _ => panic!()
};

In other words: a match with exactly two arms, the first of which extracts "the only expected variant at this point in execution" and the other a default branch which does something (e.g. panics) if that expected variant isn't found.

This seems exactly what let-else is meant for i.e. the above would be better as:

let Y(z) = x else { panic!() };

Advantage

Advantages:

  • if-let is terser than the match equivalent (sometimes collapsing 4 lines down to 1).
  • I believe let-else, is now the expected idiom for "extract the only expected variant and if it's not found something has gone wrong".

Drawbacks

No response

Example

enum E {
  Y(z),
  A(b),
  C(d)
}

fn f() {
  let z = match x {
    Y(z) => z,
    _ => p
  };
  ...
}

Could be written as:

enum E {
  Y(z),
  A(b),
  C(d)
}

fn f() {
  let Y(z) = x else { p };
  ...
}
@ltratt ltratt added the A-lint Area: New lints label May 13, 2024
@ltratt ltratt changed the title match with default branch that would better be if-let. match with default branch that would better be let-else. May 13, 2024
@y21
Copy link
Member

y21 commented May 13, 2024

This lint already exists: https://rust-lang.github.io/rust-clippy/master/index.html#/manual_let_else

warning: this could be rewritten as `let...else`
  --> src/main.rs:10:3
   |
10 | /   let z = match x {
11 | |     Y(z) => z,
12 | |     _ => todo!()
13 | |   };
   | |____^ help: consider writing: `let Y(z) = x else { todo!() };`
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else

Since it's in the pedantic category, it's allowed by default and needs to be manually enabled.

@ltratt
Copy link
Author

ltratt commented May 13, 2024

You're quite right! I've checked and this does fire on most (though not all, for reasons I haven't yet understood) instances of the idiom in our codebase. FWIW this lint doesn't feel pedantic to me, but maybe I'm biased.

@GuillaumeGomez
Copy link
Member

Then please open another issue to change the category. I think it should be in the style passes. Anyway, better to have an issue with a title related to what you suggest so you can attract more commenters. ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-lint Area: New lints
Projects
None yet
Development

No branches or pull requests

3 participants