Skip to content

Commit 0765c16

Browse files
committed
clarify why deref! and const patterns must be pure, but not guards
1 parent e8c51c0 commit 0765c16

File tree

1 file changed

+36
-0
lines changed

1 file changed

+36
-0
lines changed

text/3637-guard-patterns.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,42 @@ If guards can only appear immediately within or-patterns, then either
250250

251251
This can also be seen as a special case of the previous argument, as pattern macros fundamentally assume that patterns can be built out of composable, local pieces.
252252

253+
## Deref and Const Patterns Must Be Pure, But Not Guards
254+
255+
It may seem odd that we explicitly require `deref!` and const patterns to use pure `Deref` and `PartialEq` implementations, respectively, but allow arbitrary side effects in guards. The ultimate reason for this is that, unlike `deref!` and const patterns, guard patterns are always refutable.
256+
257+
With `deref!` patterns, we can write an impure `Deref` impl which alternates between returning `true` or `false` to get UB:
258+
```rust
259+
match EvilBox::new(false) {
260+
deref!(true) => {} // Here the `EvilBox` dereferences to `false`.
261+
deref!(false) => {} // And here to `true`.
262+
}
263+
```
264+
265+
And similarly, without the requirement of `StructuralPartialEq` we could write a `PartialEq` implementation which always returns `false`:
266+
267+
```rust
268+
const FALSE: EvilBool = EvilBool(false);
269+
const TRUE: EvilBool = EvilBool(true);
270+
271+
match EvilBool(false) {
272+
FALSE => {},
273+
TRUE => {},
274+
}
275+
```
276+
277+
However, this is not a problem with guard patterns because they already need a irrefutable alternative anyway.
278+
For example, we could rewrite the const pattern example with guard patterns as follows:
279+
280+
```rust
281+
match EvilBool(false) {
282+
x if x == FALSE => {},
283+
x if x == TRUE => {},
284+
}
285+
```
286+
287+
But this will always be a compilation error because the `match` statement is no longer assumed to be exhaustive.
288+
253289
# Prior art
254290
[prior-art]: #prior-art
255291

0 commit comments

Comments
 (0)