-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Add non_exhaustive_omitted_patterns lint related to rfc-2008-non_exhaustive #86809
Conversation
r? @davidtwco (rust-highfive has picked a reviewer for you, use r? to override) |
This comment has been minimized.
This comment has been minimized.
I think you can use
The exhaustiveness checker (the thing that checks that matches are exhaustive, FWIW) lives in |
Perfect just what I was looking for thanks! I'll leave what I have in Seems to me if we could add a way to ignore |
Okay, I actually read #84332 this time. Just to make sure I understand correctly: the goal is to lint on matches that are non exhaustive if you remove the Or put another way, this should trigger the lint? /// Latins are still figuring this out, please stand by
#[non_exhaustive]
enum Alphabet {
A,
B,
}
match foo {
Alphabet::A => {}
// This has a guard, so the match isn't exhaustive, but both A and B are mentioned
Alphabet::B if guard => {}
_ => {}
} |
Yeah that should trigger with match foo {
Alphabet::A => {}
// This has a guard, so the match isn't exhaustive, but both A and B are mentioned
Alphabet::B if guard => {}
#[deny(reachable)]
_ => {}
} |
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 is a good start. I've not checked the logic in too much detail, I will do after some initial changes are made.
There should only be a single lint name involved here - this currently uses reachable
and reachable_patterns
(reachable_patterns
being the lint itself, and reachable
being used to indicate a match expression ought to be being checked). I'd recommend changing this so that there's only reachable_patterns
(perhaps renamed to non_exhaustive_reachable_patterns
), that is allow-by-default. When you emit a lint, the logic for that will work out if it should be shown to the user based on the lint level, so you shouldn't need to check if the attribute is present or not, if the expression is annotated with a #[{allow,deny,warn}(reachable_patterns)]
then it'll fire, if not, it won't.
Given that a new lint is a user-facing change, this probably warrants a major change proposal too.
I opened an MCP rust-lang/compiler-team#445, I hope I followed the structure ok enough. The problem with the logic that is currently in the PR is that it only accounts for variants it will not take guards or nesting into account. It seems to me the options are
|
Let's not invest much more effort into this until the MCP has been looked at by the compiler team, I wouldn't want your time to go to waste if we took the wrong approach here or the MCP wasn't accepted. |
Thanks for your help, I kinda figured waiting for the MCP was the next step. I have some rough logic to check enums in the usefulness code I was going to push it just so there are 2 commits that can be referenced for an idea of what to do (since they both aren't fully functional). I think if I can make the non_exhaustive variant work it'll be much closer to working for destructuring let stmts too, so I might fiddle with that be for I push another commit, should be by the end of the day. |
6ca9879
to
5ccc800
Compare
This is now completely done in usefulness checking I removed the The lint currently only works for enums and only top-level non_exhaustive enums // works fine
#[non_exhaustive]
pub enum Bar {
A,
B(usize),
C { field: Foo },
}
// does not work
pub enum VariantNonExhaustive {
#[non_exhaustive]
Bar { x: u32 },
Baz(u32),
} For the latter to work the lint would have to be implemented for structs which it is not yet. The major change is to compute_match_usefulness and some of the functions/methods it calls If we encounter a wildcard entry for a The lint is defined in rustc_lint_defs. It uses the regular lint mechanics instead of checking for the attribute and level in the usefulness code. It emits the lint in check_match and the emitting code is here. |
This comment has been minimized.
This comment has been minimized.
5ccc800
to
eb1c98b
Compare
☔ The latest upstream changes (presumably #80357) made this pull request unmergeable. Please resolve the merge conflicts. |
eb1c98b
to
8bcb1e9
Compare
This comment has been minimized.
This comment has been minimized.
Thank you for doing this! Out of curiosity how does this handle matching multiple enums at once? For example
While thinking about this I came to the conclusion that it may not be possible to support adding the lint to the wildcard pattern itself, just to the parent statement -- could be wrong though. |
BTW I wrote this up (along with alternatives) as an RFC at https://github.com/sunshowers/rfcs/blob/unknown-non-exhaustive/text/0000-unknown-non-exhaustive.md before being pointed to this PR :) |
⌛ Testing commit 33a06b7 with merge a3b66f0209c4d1ddd6ab7d656aa94e139ebb6b55... |
💔 Test failed - checks-actions |
The job Click to see the possible cause of the failure (guessed by this bot)
|
☀️ Test successful - checks-actions |
Finished benchmarking commit (2b5ddf3): comparison url. Summary: This benchmark run did not return any relevant changes. If you disagree with this performance assessment, please file an issue in rust-lang/rustc-perf. @rustbot label: -perf-regression |
It looks like that hasn't been solved. The ui test that was added even has unstable variants in the expected output. Did that happen on purpose? This goes against the point of Opening an issue for this, as it should probably be solved before this lint hits stable. Edit: Issue: #89042 |
Ah shoot. That's on me. I assumed that the exhaustiveness code already handled those variants in the expected way so I didn't double-check. Shouldn't be too hard to solve thankfully |
Visiting for performance triage.
perhaps noise, but 🎉 nonetheless. :) |
Fix: non_exhaustive_omitted_patterns by filtering unstable and doc hidden variants Fixes: rust-lang#89042 Now that rust-lang#86809 has been merged there are cases (std::io::ErrorKind) where unstable feature gated variants were included in warning/error messages when the feature was not turned on. This filters those variants out of the return of `SplitWildcard::new`. Variants marked `doc(hidden)` are filtered out of the witnesses list in `Usefulness::apply_constructor`. Probably worth a perf run :shrug: since this area can be sensitive.
Fixes: #84332
This PR adds
non_exhaustive_omitted_patterns
, an allow by default lint that is triggered when anon_exhaustive
type is missing explicit patterns. The warning or deny attribute can be put above the wildcard_
pattern on enums or on the expression for enums or structs. The lint is capable of warning about multiple types within the same pattern. This lint will not be triggered forif let ..
patterns.