You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: text/3637-guard-patterns.md
+29-15Lines changed: 29 additions & 15 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -76,29 +76,43 @@ x @ A(..) if pred <=> (x @ A(..)) if pred
76
76
A(..) |B(..) ifpred<=> (A(..) |B(..)) ifpred
77
77
```
78
78
79
-
## Interaction with Expression Operators
79
+
## Precedence Relative to `|`
80
80
81
-
The or-pattern operator and the bitwise OR operator both use the `|` token. This creates a parsing ambiguity:
81
+
Consider the following match expression:
82
82
83
83
```rust
84
-
// How is this parsed?
85
-
falseiffoo|true
86
-
// As a guard pattern nested in an or-pattern?
87
-
(falseiffoo) |true
88
-
// Or as a pattern guarded by a bitwise OR operation?
89
-
falseif (foo|true)
84
+
matchfoo {
85
+
A|Bifc|d=> {},
86
+
}
87
+
```
88
+
89
+
This match arm is currently parsed as `(A | B) if (c | d)`, with the first `|` being the or-operator on patterns and the second being the bitwise OR operator on expressions. Therefore, to maintain backwards compatability, `if` must have lower precedence than `|` on both sides (or equivalently, for both meanings of `|`). For that reason, guard patterns nested within or-patterns must be explicitly parenthesized:
90
+
91
+
```rust
92
+
// This is not an or-pattern of guards:
93
+
aifb|cifd
94
+
<=> (aif (b|c)) ifd
95
+
96
+
// Instead, write
97
+
(aifb) | (cifd)
90
98
```
91
99
92
-
For that reason, guard patterns nested within or-patterns must be explicitly parenthesized.
93
-
Otherwise, the `|` will be parsed as a bitwise OR to maintain backwards compatability with match arm guards.
100
+
## In Assignment-Like Contexts
94
101
95
-
There's a similar ambiguity between `=` used as the assignment operator within the guard
96
-
and used outside to indicate assignment to the pattern (e.g. in `if`-`let`, `while let`, etc.).
102
+
There's an ambiguity between `=` used as the assignment operator within the guard
103
+
and used outside to indicate assignment to the pattern (e.g. in `iflet`)
97
104
Therefore guard patterns appearing at the top level in those places must also be parenthesized:
98
105
99
106
```rust
100
-
whileletxifguard(x) =foo() {} // not allowed
101
-
whilelet (xifguard(x)) =foo() {} // allowed
107
+
// Not allowed:
108
+
letxifguard(x) =foo() {}
109
+
ifletxifguard(x) =foo() {}
110
+
whileletxifguard(x) =foo() {}
111
+
112
+
// allowed
113
+
let (xifguard(x)) =foo() {} // Note that this would still error after parsing, since guard patterns are always refutable.
114
+
iflet (xifguard(x)) =foo() {}
115
+
whilelet (xifguard(x)) =foo() {}
102
116
```
103
117
104
118
Therefore the syntax for patterns becomes
@@ -111,7 +125,7 @@ Therefore the syntax for patterns becomes
With `if let`, `while let`, and `for`expressions now using `PatternNoTopGuard`. `let` statements can continue to use `PatternNoTopAlt`.
128
+
With `if let` and `while let`expressions now using `PatternNoTopGuard`. `let` statements and function parameters can continue to use `PatternNoTopAlt`.
0 commit comments