lang (patterns | exhaustiveness | control-flow)
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 lint which is allowed to be disabled by such macros.
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 for a lint that does not seem to be related to the problem.
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.
#[allow(unreachable_patterns)]
match $val {
$p => { $b; },
_ => ()
}
The following cannot be used, so the previous must be. An #[allow(irrefutable_let_pattern)]
is used so that the error-by-default lint does not appear to the user.
if let $p = $val {
$b
}
irrefutable if-let-pattern
and similar patterns to an error-by-default
lint that can be disabled by an #[allow]
statementirrefutable_let_pattern
Code Example (explicit):
#[allow(irrefutable_let_pattern)]
if let _ = 'a' {
println!("Hello World");
}
Code Example (implicit):
macro_rules! check_five {
($p:pat) => {{
#[allow(irrefutable_let_pattern)]
if let $p = 5 {
println!("Pattern matches five");
}
}};
}
This can be taught by changing the second version of The Book to not explicitly say that it is not allowed. Adding that it is a lint that can be disabled.
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)]
.