-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Added restriction lint: pattern-type-mismatch #4841
Conversation
Hello, I'd like to propose a new off-by-default restriction lint called DescriptionThe purpose of the lint is to enforce that patterns accurately represent the types they As far as I'm aware, this would currently only be triggered when default binding modes I have avoided mentioning default binding modes in the name and the description. Due to past By going this route, it should be easy for people who are looking for these guarantees to MotivationThe lint allows enforcing the following code properties:
DetailsThe lint would guard the following language constructs:
The suggestion to the user takes the following form:
cargo fixOn the surface, it seems like this should be automatable. Some of the bindings would stay I'm also of the opinion that since one purpose of the lint is to give ownership hints in matched Given that, I would argue that this should not be automatically fixed. Some QuestionsAs this is my first lint, I'm unsure about a few things:
I'm sure there are other things I'll need to fix as well. The implementation works by recursing through the involved types and patterns, and looking |
It seems CI fails because the I'm unsure how to proceed. |
I upped the STDERR limit to a round 300 for now. I'm having trouble understanding the new failures though. It seems some |
$ cargo +master install --force --debug --path .
# checkout a crate and `cd <crate>`
$ LD_LIBRARY_PATH=$(rustc +master --print=sysroot)/lib cargo clippy -- --Wclippy::pattern_type_mismatch |
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 really like the concept of the lint and think, that this could really help Rust beginners to understand how pattern matching in Rust works. I'll try to do a in depth review ASAP.
@flip1995 Very helpful, thank you! I'll have a go at splitting up the STDERR files and reset the limit down to 275. |
That would be great. I think a good split would be into the different syntax constructs. Make sure to add tests that should trigger the lint and tests that shouldn't trigger it. |
I've split up the test file into a subdirectory. I tried to use the opportunity to reorganize the tests themselves to be a bit more easy to follow. The different kinds of syntaxes are actually now in one file, as the tests there can be rather simple. Instead, I've split it up the different pattern constructs (structs, tuples, alternatives). That's the complex part of the actual lint I feel, and has more variation due to the different forms types can have. I also removed some probably redundant tests (functions vs associated functions) that I had added more for the purpose of discovering the compiler's API and ensuring my assumptions hold. Edit: I also organized it so that sections that trigger the lint and sections that don't are next to each other. And all linted constructs should now also have examples that are not linted against. |
☔ The latest upstream changes (presumably #4821) made this pull request unmergeable. Please resolve the merge conflicts. |
A procedural question: Should I keep rebasing the PR or would the forced pushes interfere with reviewing? |
You can keep rebasing it. It doesn't make a difference for reviewing. On the other hand, once I get to reviewing this I can ping you, so you don't have to rebase every other day. |
fd76273
to
1378f58
Compare
Squashed, rebased and caught up with recent changes in master. |
☔ The latest upstream changes (presumably #5058) made this pull request unmergeable. Please resolve the merge conflicts. |
1378f58
to
235a035
Compare
Pushed some changes to catch up to master. There are still some errors when trying to compile, but since they're coming from another lint I assume this is a clippy/nightly divergence issue. |
☔ The latest upstream changes (presumably #5148) made this pull request unmergeable. Please resolve the merge conflicts. |
235a035
to
3010bda
Compare
☔ The latest upstream changes (presumably #5029) made this pull request unmergeable. Please resolve the merge conflicts. |
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 finally got to take a look at this. Sorry or the way to long wait time...
I think this is especially a great lint for newcomers to learn pattern magic and the rust magic behind it. That being said, I also think the message use
*to dereference the match expression or explicitly match against a
&_ pattern and adjust the enclosed variable bindings
is too generic for newcomers to understand and apply. It would be great, if this message could point to where this borrows or derefs should happen. Something like this:
error: type of pattern does not match the expression type
--> $DIR/mutability.rs:9:9
|
LL | Some(x) => (),
| ^^^^^^^
|
= help: use `*` to dereference the match expression
|
LL | match *expr {
| ^^^^^
|
= help: or explicitly match against a `&_` pattern...
|
LL | &Some(x) => (),
| ^^^^^^^^
|
= help: ...and adjust the enclosed variable bindings
|
LL | Some(&x) => (),
| ^^
= help: ...also here // add more hints recursively
...
I can see, that the recursive suggestion generation might be too much to ask. But I think, this lint would strongly benefit from at least building the suggestion for the top level deref or the &
match. You can optionally add suggestions/help messages with span_lint_and_then(.., |db| { db.span_{help,suggestion,...})
. See also the DiagnosticBuilder
documentation. Recently I implemented similar suggestion generation here:
rust-clippy/clippy_lints/src/types.rs
Lines 686 to 693 in 5924fa6
fn lint_unit_args(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args_to_recover: &[&Expr<'_>]) { | |
let mut applicability = Applicability::MachineApplicable; | |
let (singular, plural) = if args_to_recover.len() > 1 { | |
("", "s") | |
} else { | |
("a ", "") | |
}; | |
span_lint_and_then( |
@flip1995 Apologies for taking a while. I can see where the expanded diagnostic including bindings can be useful. I think expanding it for nested patterns or those with many bindings might make things less clear. There are advantages to the extra information when the lint is used as a teaching utility, but outside of that it would potentially be a very long version of a type mismatch error. Do you have a preference as to how the diagnostic should look for the cases where bindings aren't mentioned? Should it just stay the way it currently is implemented for those? |
Maybe add a configuration option for this lint:
Without the configuration set, this help message should be span-less or you can just point at bindings like this:
|
As I said above, the recursive suggestion for all bindings might be too hard to implement for a fist version and we can add the configuration option and inner binding suggestions later. |
Thanks for contributing to Clippy! Sadly this PR was not updated in quite some time. If you waited on input from a reviewer, we're sorry that this fell under the radar. If you want to continue to work on this, just reopen the PR and/or ping a reviewer. |
Thanks, this looks really good now! Also big thanks for sticking around so long and be patiently waiting for my reviews. @bors r+ |
📌 Commit 77b6130 has been approved by |
Added restriction lint: pattern-type-mismatch changelog: Added a new restriction lint `pattern-type-mismatch`. This lint is especially helpful for beginners learning about the magic behind pattern matching. (This explanation might be worth to include in the next changelog.)
💔 Test failed - checks-action_test |
@flip1995 Thanks! :D And a very big thanks to you for being so helpful! |
@bors r+ |
💡 This pull request was already approved, no need to approve it again.
|
📌 Commit 77b6130 has been approved by |
Added restriction lint: pattern-type-mismatch changelog: Added a new restriction lint `pattern-type-mismatch`. This lint is especially helpful for beginners learning about the magic behind pattern matching. (This explanation might be worth to include in the next changelog.)
💔 Test failed - checks-action_test |
You need to remove the first LT parameter of every |
77b6130
to
c0fd452
Compare
Thanks, and done! |
@bors r+ Thanks! Let's get this finally through 🚀 |
📌 Commit c0fd452 has been approved by |
☀️ Test successful - checks-action_dev_test, checks-action_remark_test, checks-action_test |
changelog: Added a new restriction lint
pattern-type-mismatch
. This lint is especially helpful for beginners learning about the magic behind pattern matching. (This explanation might be worth to include in the next changelog.)