|
| 1 | +# Proposal |
| 2 | + |
| 3 | +Allow pattern matching through types that impl `Deref` or `DerefMut`. |
| 4 | + |
| 5 | +## Summary and problem statement |
| 6 | + |
| 7 | +Currently in rust, matching is blocked by bounderies like smart pointers, containers, and some wrappers. |
| 8 | +To solve this problem you would need to either use if let guards (unstable), or nested match/if-let. |
| 9 | +The former is limited to one such level, and the latter can become excessive for deeply nested types. |
| 10 | +To solve this, it is proposed propose that "deref patterns" be added, to allow for such matching to be performed. |
| 11 | + |
| 12 | +An exception to the above problem, is that `Box<T>` can be matched with `feature(box_patterns)`. |
| 13 | +However, this is magic behaviour of box, and a goal of this project is to remove or reduce that magic. |
| 14 | + |
| 15 | +The proposed solution has a number of unanswered questions, including the syntax for patterns, whether or not to limit to standard library types, |
| 16 | + and how to allow exhaustive patterns soundly if not limited to standard library types. |
| 17 | + |
| 18 | +### Exhaustive Patterns and Soundness |
| 19 | + |
| 20 | +One current issue with the proposed deref patterns is that if applied generally to any type that implements `Deref`, |
| 21 | +it cannot soundly permit exhaustive pattern matching, as a malicious `Deref` impl could return a different value each time. |
| 22 | +An trivial example would be `Deref` impl that returns a static reference to an enum value that is chosen randomly |
| 23 | +There are currently 3 different possible solutions: |
| 24 | +* Do not treat deref patterns as exhausitve |
| 25 | +* Restrict deref patterns to (possibly a subset of) standard library types |
| 26 | +* Expose an unsafe lang item trait called `DerefPure`, and restrict deref patterns to implementors of that trait |
| 27 | + |
| 28 | +This initial Project Group will persue the second option, that is limiting deref patterns to a subset of standard library types. Other projects may, in the future, expand upon the work from this project to include user-provided types. The project will determine the critera for a subset needed for sound exhaustive matching, and propose an initial subset to support. |
| 29 | + |
| 30 | + |
| 31 | +## Motivation, use-cases, and solution sketches |
| 32 | + |
| 33 | +Recursive types necessarily include smart pointers, even when you could normally match through them. |
| 34 | +For example, in a work in progress proc-macro to support restricted variadic generics, the parser needed to match "fold expressions", which take the form `(<pattern> <op> ...)`. With deref patterns, this could be implemented using `Expr::Paren(ParenExpr{expr: Expr::Binary(ExprBinary{ left, op, right: Expr::Verbatim(t), ..}), ..})`. However, this is currently not possible, and required nested matches. |
| 35 | +This generalizes to any case where you need to check some pattern, but hit a deref boundery. |
| 36 | + |
| 37 | + |
| 38 | + |
| 39 | +## Prioritization |
| 40 | + |
| 41 | +This likely does not fit into any of the listed priorities, though it may be considered "Targeted ergonomic wins and extensions". |
| 42 | + |
| 43 | +## Links and related work |
| 44 | + |
| 45 | +This has been discussed on the Rust Internals Forum at <https://internals.rust-lang.org/t/somewhat-random-idea-deref-patterns/13813>, |
| 46 | +as well as on zulip at <https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/Deref.20patterns>. |
| 47 | + |
| 48 | +A tracking document of all currently discussed questions and potential answers can be found here <https://hackmd.io/GBTt4ptjTh219SBhDCPO4A>. |
| 49 | + |
| 50 | +Prior discussions raised on the IRLO thread: |
| 51 | +* https://github.com/rust-lang/rfcs/pull/462 |
| 52 | +* https://github.com/rust-lang/rfcs/issues/2099 |
| 53 | +* https://github.com/rust-lang/rfcs/blob/master/text/0809-box-and-in-for-stdlib.md |
| 54 | + |
| 55 | +## Initial people involved |
| 56 | + |
| 57 | +Initially, Connor Horman and Nadriel on zulip would be involved |
0 commit comments