From d04554515873fa0b18473be50659edf5a860b4d2 Mon Sep 17 00:00:00 2001 From: "WATGAMER\\snmalton" Date: Thu, 27 Jul 2017 13:08:02 -0400 Subject: [PATCH 01/11] Inital RFC commit --- text/0000-allow-if-let-irrefutables.md | 54 ++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 text/0000-allow-if-let-irrefutables.md diff --git a/text/0000-allow-if-let-irrefutables.md b/text/0000-allow-if-let-irrefutables.md new file mode 100644 index 00000000000..6c50496df27 --- /dev/null +++ b/text/0000-allow-if-let-irrefutables.md @@ -0,0 +1,54 @@ +- 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`. + +# 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 a compiler allow. +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 +if let $p = $val { + $b +} +``` +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. + +```rust +#[allow(unreachable_patterns)] +match $val { + $p => { $b; }, + _ => () +} +``` + + +# Detailed design +[design]: #detailed-design + +1. Remove the error from `irrefutable if-let pattern`. Allow it to compile as a tautology. +2. Remove the error from `irrefutable while-let pattern`. Allow it to compile as a tautology (maybe a loop). + +# 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. + +# Drawbacks +[drawbacks]: #drawbacks + +It allows programmers to manually write the line `if let _ = expr { } else { }` which is generally obfuscating and not desirable. However, a different RFC should solve this. + +# Alternatives +[alternatives]: #alternatives + +# Unresolved questions +[unresolved]: #unresolved-questions From 5020914fcdac6ab110b4161442bce31569451cd7 Mon Sep 17 00:00:00 2001 From: "WATGAMER\\snmalton" Date: Thu, 27 Jul 2017 13:50:19 -0400 Subject: [PATCH 02/11] Added some alternatives --- text/0000-allow-if-let-irrefutables.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/text/0000-allow-if-let-irrefutables.md b/text/0000-allow-if-let-irrefutables.md index 6c50496df27..69c7af144f5 100644 --- a/text/0000-allow-if-let-irrefutables.md +++ b/text/0000-allow-if-let-irrefutables.md @@ -50,5 +50,8 @@ It allows programmers to manually write the line `if let _ = expr { } else { }` # 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. +* Turn the error into a lint that errors by default. Unreachable match arms are usually wrong except in some macros and that's why you can disable the warning there with #[allow(unreachable_patterns)]. The same goes for irrefutable if/while-let patterns, so it only seems natural to apply a similar solution. This also means that `#[allow]` statements need to be allowed. + # Unresolved questions [unresolved]: #unresolved-questions From 19f742b4314db3ab66d1a0217ceb14a51218f837 Mon Sep 17 00:00:00 2001 From: "WATGAMER\\snmalton" Date: Thu, 3 Aug 2017 15:18:18 -0400 Subject: [PATCH 03/11] Chaning the request to making it an error-by-default lint --- text/0000-allow-if-let-irrefutables.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/text/0000-allow-if-let-irrefutables.md b/text/0000-allow-if-let-irrefutables.md index 69c7af144f5..e29c6d81adb 100644 --- a/text/0000-allow-if-let-irrefutables.md +++ b/text/0000-allow-if-let-irrefutables.md @@ -34,24 +34,23 @@ match $val { # Detailed design [design]: #detailed-design -1. Remove the error from `irrefutable if-let pattern`. Allow it to compile as a tautology. -2. Remove the error from `irrefutable while-let pattern`. Allow it to compile as a tautology (maybe a loop). +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 # 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, a different RFC should solve this. +It allows programmers to manually write the line `if let _ = expr { } else { }` which is generally obfuscating and not desirable. However, this will not be explicitly allowed with the `#[allow]`. # 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. -* Turn the error into a lint that errors by default. Unreachable match arms are usually wrong except in some macros and that's why you can disable the warning there with #[allow(unreachable_patterns)]. The same goes for irrefutable if/while-let patterns, so it only seems natural to apply a similar solution. This also means that `#[allow]` statements need to be allowed. # Unresolved questions [unresolved]: #unresolved-questions From b8179dcc55562dfad81c9e983b4ea419a20e796f Mon Sep 17 00:00:00 2001 From: "WATGAMER\\snmalton" Date: Fri, 4 Aug 2017 10:17:11 -0400 Subject: [PATCH 04/11] Added the macro reason for why this should be added to the language. A proposed lint name and some code examples --- text/0000-allow-if-let-irrefutables.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/text/0000-allow-if-let-irrefutables.md b/text/0000-allow-if-let-irrefutables.md index e29c6d81adb..bab730f950d 100644 --- a/text/0000-allow-if-let-irrefutables.md +++ b/text/0000-allow-if-let-irrefutables.md @@ -7,6 +7,7 @@ [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 @@ -35,6 +36,27 @@ match $val { [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)] +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 From 2929bacc69334ce9e222513609fab41ad18491ce Mon Sep 17 00:00:00 2001 From: "WATGAMER\\snmalton" Date: Fri, 4 Aug 2017 13:03:42 -0400 Subject: [PATCH 05/11] Changed lint name to underscores --- text/0000-allow-if-let-irrefutables.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/text/0000-allow-if-let-irrefutables.md b/text/0000-allow-if-let-irrefutables.md index bab730f950d..425b7e3c993 100644 --- a/text/0000-allow-if-let-irrefutables.md +++ b/text/0000-allow-if-let-irrefutables.md @@ -36,11 +36,11 @@ match $val { [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` +2. Proposed lint name: `irrefutable_let_pattern` Code Example (explicit): ```rust -#[allow(irrefutable-let-pattern)] +#[allow(irrefutable_let_pattern)] if let _ = 'a' { println!("Hello World"); } @@ -50,7 +50,7 @@ Code Example (implicit): ```rust macro_rules! check_five { ($p:pat) => {{ - #[allow(irrefutable-let-pattern)] + #[allow(irrefutable_let_pattern)] if let $p = 5 { println!("Pattern matches five"); } From 505cf4b9696d7fb2b1e39688ce74d2f7c38b9fcd Mon Sep 17 00:00:00 2001 From: "WATGAMER\\snmalton" Date: Mon, 28 Aug 2017 12:35:42 -0400 Subject: [PATCH 06/11] Moved around an example and change the wording to be more clear in the Drawbacks sections --- text/0000-allow-if-let-irrefutables.md | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/text/0000-allow-if-let-irrefutables.md b/text/0000-allow-if-let-irrefutables.md index 425b7e3c993..ccb28bd8f29 100644 --- a/text/0000-allow-if-let-irrefutables.md +++ b/text/0000-allow-if-let-irrefutables.md @@ -16,13 +16,6 @@ The use cases for this is in the creation of macros where patterns are allowed b 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 -if let $p = $val { - $b -} -``` -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. - ```rust #[allow(unreachable_patterns)] match $val { @@ -31,6 +24,12 @@ match $val { } ``` +```rust +if let $p = $val { + $b +} +``` +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 @@ -67,9 +66,9 @@ 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 not be explicitly allowed with the `#[allow]`. +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 +# Alternatives4 [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. From c7904e5bd7ab1e4072844877d70162d0ce2b448c Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Wed, 30 Aug 2017 13:25:23 -0400 Subject: [PATCH 07/11] Fixed the link to the book --- text/0000-allow-if-let-irrefutables.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-allow-if-let-irrefutables.md b/text/0000-allow-if-let-irrefutables.md index ccb28bd8f29..7a6e5c6e6c5 100644 --- a/text/0000-allow-if-let-irrefutables.md +++ b/text/0000-allow-if-let-irrefutables.md @@ -60,7 +60,7 @@ macro_rules! check_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. +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 From d61be78df53988cce25abbd0b0eb6b90db4d8721 Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Wed, 30 Aug 2017 13:25:45 -0400 Subject: [PATCH 08/11] Removed a 4 --- text/0000-allow-if-let-irrefutables.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-allow-if-let-irrefutables.md b/text/0000-allow-if-let-irrefutables.md index 7a6e5c6e6c5..275c220f017 100644 --- a/text/0000-allow-if-let-irrefutables.md +++ b/text/0000-allow-if-let-irrefutables.md @@ -68,7 +68,7 @@ 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)]`. -# Alternatives4 +# 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. From 3d97cf1c8617f823dfb4ea097b3f1980cc347b09 Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Thu, 31 Aug 2017 21:35:17 -0400 Subject: [PATCH 09/11] Reworded the motivation statement to be more clear --- text/0000-allow-if-let-irrefutables.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-allow-if-let-irrefutables.md b/text/0000-allow-if-let-irrefutables.md index 275c220f017..e6e151bee38 100644 --- a/text/0000-allow-if-let-irrefutables.md +++ b/text/0000-allow-if-let-irrefutables.md @@ -12,7 +12,7 @@ The current state breaks macros who want to accept patterns generically and this # 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 a compiler allow. +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. From 99a71b89ef63fca813839a11fc7f54553ce96f97 Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Fri, 8 Sep 2017 16:24:25 -0400 Subject: [PATCH 10/11] Some small wording updates Changed the flow of the motivation section so as to better distinguish the code examples. Added the word 'lint' as it was missing from the summary section --- text/0000-allow-if-let-irrefutables.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/text/0000-allow-if-let-irrefutables.md b/text/0000-allow-if-let-irrefutables.md index e6e151bee38..e29f047d5f8 100644 --- a/text/0000-allow-if-let-irrefutables.md +++ b/text/0000-allow-if-let-irrefutables.md @@ -7,12 +7,12 @@ [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. +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. # 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 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. @@ -23,13 +23,13 @@ match $val { _ => () } ``` +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. ```rust if let $p = $val { $b } ``` -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 From 394aa3aaf5de69900a3df5c0a72aebb561d8482a Mon Sep 17 00:00:00 2001 From: Aaron Turon Date: Mon, 11 Sep 2017 09:15:03 -0700 Subject: [PATCH 11/11] RFC 2086: Allow Irrefutable Patterns in if-let and while-let statements --- ...-let-irrefutables.md => 2086-allow-if-let-irrefutables.md} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename text/{0000-allow-if-let-irrefutables.md => 2086-allow-if-let-irrefutables.md} (96%) diff --git a/text/0000-allow-if-let-irrefutables.md b/text/2086-allow-if-let-irrefutables.md similarity index 96% rename from text/0000-allow-if-let-irrefutables.md rename to text/2086-allow-if-let-irrefutables.md index e29f047d5f8..024a922764f 100644 --- a/text/0000-allow-if-let-irrefutables.md +++ b/text/2086-allow-if-let-irrefutables.md @@ -1,7 +1,7 @@ - Feature Name: allow_if_let_irrefutables - Start Date: 2017-07-27 -- RFC PR: -- Rust Issue: +- RFC PR: https://github.com/rust-lang/rfcs/pull/2086 +- Rust Issue: https://github.com/rust-lang/rust/issues/44495 # Summary [summary]: #summary