-
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
RFC: Allow Irrefutable Patterns in if-let and while-let statements #2086
Changes from 9 commits
d045545
5020914
19f742b
b8179dc
2929bac
505cf4b
c7904e5
d61be78
3d97cf1
99a71b8
394aa3a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
- Feature Name: allow_if_let_irrefutables | ||
- Start Date: 2017-07-27 | ||
- RFC PR: | ||
- Rust Issue: | ||
|
||
# Summary | ||
[summary]: #summary | ||
|
||
Currently when using an if let statement and an irrefutable pattern (read always match) is used the compiler complains with an `E0162: irrefutable if-let pattern`. | ||
The current state breaks macros who want to accept patterns generically and this RFC proposes changing this error to an error-by-default which is allowed to be disabled by such macros. | ||
|
||
# Motivation | ||
[motivation]: #motivation | ||
|
||
The use cases for this is in the creation of macros where patterns are allowed because to support the `_` patterns the code has to be rewritten to be both much larger and include an \[#allow\] statement. | ||
The expected outcome is for irrefutable patterns to be compiled to a tautology and have the if block accept it as if it was `if true { }`. | ||
To support this, currently you must do something roughly the following, which seems to counteract the benefit of having if-let and while-let in the spec. | ||
|
||
```rust | ||
#[allow(unreachable_patterns)] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Question and/or Presentation nit: Is this If my inference is correct in that the "the following" is meant to denote the For example:
|
||
match $val { | ||
$p => { $b; }, | ||
_ => () | ||
} | ||
``` | ||
|
||
```rust | ||
if let $p = $val { | ||
$b | ||
} | ||
``` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These two adjacent code blocks are confusing, especially since the second one starts a new thought. I picture something more along the lines of:
|
||
Cannot be used, so the original match must be. The `allow` is forced so that the warning does not appear to the user of it since `_` won't be matched if `$p` is irrefutable. | ||
|
||
# Detailed design | ||
[design]: #detailed-design | ||
|
||
1. Change the compiler error `irrefutable if-let-pattern` and similar patterns to an `error-by-default` lint that can be disabled by an `#[allow]` statement | ||
2. Proposed lint name: `irrefutable_let_pattern` | ||
|
||
Code Example (explicit): | ||
```rust | ||
#[allow(irrefutable_let_pattern)] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This example still won't work due to #2086 (comment). |
||
if let _ = 'a' { | ||
println!("Hello World"); | ||
} | ||
``` | ||
|
||
Code Example (implicit): | ||
```rust | ||
macro_rules! check_five { | ||
($p:pat) => {{ | ||
#[allow(irrefutable_let_pattern)] | ||
if let $p = 5 { | ||
println!("Pattern matches five"); | ||
} | ||
}}; | ||
} | ||
``` | ||
|
||
# How We Teach This | ||
[how-we-teach-this]: #how-we-teach-this | ||
|
||
This can be taught by changing the second version of [The Book](https://doc.rust-lang.org/book/second-edition/ch18-02-refutability.html) to not explicitly say that it is not allowed. | ||
Adding that it is a lint that can be disabled. | ||
|
||
# Drawbacks | ||
[drawbacks]: #drawbacks | ||
|
||
It allows programmers to manually write the line `if let _ = expr { } else { }` which is generally obfuscating and not desirable. However, this will only be allowed with an explicit `#[allow(irrefutable_let_pattern)]`. | ||
|
||
# Alternatives | ||
[alternatives]: #alternatives | ||
|
||
* The trivial alternative: Do nothing. As your motivation explains, this only matters for macros anyways plus there already is an acceptable workaround (match). Code that needs this frequently can just package this workaround in its own macro and be done. | ||
|
||
# Unresolved questions | ||
[unresolved]: #unresolved-questions |
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.
error-by-default lint?