Skip to content

Commit 93fe27d

Browse files
committed
RFC: Alternatives in patterns
1 parent 1fea0c8 commit 93fe27d

File tree

1 file changed

+95
-0
lines changed

1 file changed

+95
-0
lines changed

text/0000-alternatives-in-patterns.md

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
- Feature Name: Alternatives in patterns
2+
- Start Date: 2016-02-14
3+
- RFC PR: (leave this empty)
4+
- Rust Issue: (leave this empty)
5+
6+
# Summary
7+
[summary]: #summary
8+
Extend the pattern syntax for alternatives in `match` statement, allow alternatives for pattern matching in `let` and `if let` statements.
9+
10+
# Motivation
11+
[motivation]: #motivation
12+
13+
Rust allows alternatives ( `|` ) in pattern syntax for `match`, but only for 'top-level' of pattern.
14+
This aims to reduce verbosity in certain examples and increase expressiveness.
15+
16+
Also, this RFC proposes to allow alternatives in `let` or `if let` statements.
17+
18+
# Detailed design
19+
[design]: #detailed-design
20+
21+
## Expand usage of alternatives to 'deeper levels'
22+
Imagine a type:
23+
```rust
24+
#[derive(Clone, Copy)] struct NewType (Result<String,String>, u8);
25+
```
26+
27+
Exhaustive `match` statement for this type would look like this:
28+
```rust
29+
match new_type {
30+
NewType(Ok(e), num) | NewType(Err(e), num) => println!("ok with {}: {}", num, e)
31+
}
32+
```
33+
34+
This RFC proposes a following replacement:
35+
```rust
36+
match new_type {
37+
NewType(Ok(e) | Err(e), num) => println!("ok with {}: {}", num, e)
38+
}
39+
```
40+
41+
42+
Little bit more complicated example:
43+
```rust
44+
#[derive(Clone, Copy)] enum Test { First, Second }
45+
//Current Rust:
46+
match (test1, test2) {
47+
(First, First) | (First, Second) | (Second, First) | (Second, Second) => println!("matches")
48+
}
49+
//This RFC proposes:
50+
51+
match (test1, test2) {
52+
(First| Second, First | Second) => println!("matches")
53+
}
54+
```
55+
56+
### Allow alternatives in `let` statements
57+
Currently expressions like `Ok(e) | Err(e)` are not allowed in `let` or `if let` statements, which brings inconsistence to pattern matching.
58+
This RFC proposes following to be allowed:
59+
```rust
60+
if let First | Second = three_variants_enum {}
61+
let Ok(e) | Err(e) = result;
62+
```
63+
64+
#### Irrefutable patterns
65+
Patterns in `let` statements must be irrefutable - meaning they must cover every possible variant:
66+
```rust
67+
enum Three{ First(u8), Second(u8), Third(u8) }
68+
//...
69+
let First(u) | Second(u) = three; //Not allowed!
70+
```
71+
72+
Patterns in `if let` statements should be disallowed to be irrefutable, it means they are not allowed to cover every possible variant:
73+
```rust
74+
if let Ok(e) | Err(e) = result {
75+
//Not allowed!
76+
} else {}
77+
```
78+
If pattern is irrefutable, then an `else`-branch will never be executed, and `if` will be redundant.
79+
80+
# Drawbacks
81+
[drawbacks]: #drawbacks
82+
83+
These features, probably, are not easy to implement.
84+
85+
# Alternatives
86+
[alternatives]: #alternatives
87+
88+
- **This is a subset of [#99](https://github.com/rust-lang/rfcs/pull/99).** The original RFC was postponed and as suggested by [#1456](https://github.com/rust-lang/rfcs/issues/1456#issuecomment-173943563) a new RFC was created with a link to postponed one.
89+
- **Implement the proposal only for `match`.** This has a downside of further increased inconsistence.
90+
- **Allow irrefutable patterns in `if let` statements.** This way, `else`-branch will not always execute. If so, a warning about unreachable code should be emitted.
91+
92+
# Unresolved questions
93+
[unresolved]: #unresolved-questions
94+
95+
None yet.

0 commit comments

Comments
 (0)