Skip to content

Commit

Permalink
RFC: Alternatives in patterns
Browse files Browse the repository at this point in the history
  • Loading branch information
White-Oak committed Feb 15, 2016
1 parent 1fea0c8 commit 93fe27d
Showing 1 changed file with 95 additions and 0 deletions.
95 changes: 95 additions & 0 deletions text/0000-alternatives-in-patterns.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
- Feature Name: Alternatives in patterns
- Start Date: 2016-02-14
- RFC PR: (leave this empty)
- Rust Issue: (leave this empty)

# Summary
[summary]: #summary
Extend the pattern syntax for alternatives in `match` statement, allow alternatives for pattern matching in `let` and `if let` statements.

# Motivation
[motivation]: #motivation

Rust allows alternatives ( `|` ) in pattern syntax for `match`, but only for 'top-level' of pattern.
This aims to reduce verbosity in certain examples and increase expressiveness.

Also, this RFC proposes to allow alternatives in `let` or `if let` statements.

# Detailed design
[design]: #detailed-design

## Expand usage of alternatives to 'deeper levels'
Imagine a type:
```rust
#[derive(Clone, Copy)] struct NewType (Result<String,String>, u8);
```

Exhaustive `match` statement for this type would look like this:
```rust
match new_type {
NewType(Ok(e), num) | NewType(Err(e), num) => println!("ok with {}: {}", num, e)
}
```

This RFC proposes a following replacement:
```rust
match new_type {
NewType(Ok(e) | Err(e), num) => println!("ok with {}: {}", num, e)
}
```


Little bit more complicated example:
```rust
#[derive(Clone, Copy)] enum Test { First, Second }
//Current Rust:
match (test1, test2) {
(First, First) | (First, Second) | (Second, First) | (Second, Second) => println!("matches")
}
//This RFC proposes:

match (test1, test2) {
(First| Second, First | Second) => println!("matches")
}
```

### Allow alternatives in `let` statements
Currently expressions like `Ok(e) | Err(e)` are not allowed in `let` or `if let` statements, which brings inconsistence to pattern matching.
This RFC proposes following to be allowed:
```rust
if let First | Second = three_variants_enum {}
let Ok(e) | Err(e) = result;
```

#### Irrefutable patterns
Patterns in `let` statements must be irrefutable - meaning they must cover every possible variant:
```rust
enum Three{ First(u8), Second(u8), Third(u8) }
//...
let First(u) | Second(u) = three; //Not allowed!
```

Patterns in `if let` statements should be disallowed to be irrefutable, it means they are not allowed to cover every possible variant:
```rust
if let Ok(e) | Err(e) = result {
//Not allowed!
} else {}
```
If pattern is irrefutable, then an `else`-branch will never be executed, and `if` will be redundant.

# Drawbacks
[drawbacks]: #drawbacks

These features, probably, are not easy to implement.

# Alternatives
[alternatives]: #alternatives

- **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.
- **Implement the proposal only for `match`.** This has a downside of further increased inconsistence.
- **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.

# Unresolved questions
[unresolved]: #unresolved-questions

None yet.

0 comments on commit 93fe27d

Please sign in to comment.