From 5eecccfeb849ebba847951130eb675306c8eccdc Mon Sep 17 00:00:00 2001 From: Connor Horman Date: Tue, 26 Jan 2021 16:25:11 -0500 Subject: [PATCH 1/6] Create deref-patterns.md --- projects/deref-patterns.md | 46 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 projects/deref-patterns.md diff --git a/projects/deref-patterns.md b/projects/deref-patterns.md new file mode 100644 index 0000000..d41faf8 --- /dev/null +++ b/projects/deref-patterns.md @@ -0,0 +1,46 @@ +# Proposal + +Allow pattern matching through types that impl `Deref` or `DerefMut`. + +## Summary and problem statement + +Currently in rust, matching is blocked by bounderies like smart pointers, containers, and some wrappers. +To solve this problem you would need to either use if let guards (unstable), or nested match/if-let. +The former is limited to one such level, and the latter can become excessive for deeply nested types. +To solve this, I propose that "deref patterns" be added, to allow for such matching to be performed. + +An exception to the above problem, is that `Box` can be matched with `feature(box_patterns)`. +However, this is magic behaviour of box, and I am not a fan of this kind of magic. + +The proposed solution has a number of unanswered questions, including the syntax for patterns, whether or not to limit to standard library types, + and how to allow exhaustive patterns soundly if not limited to standard library types. + + +## Motivation, use-cases, and solution sketches + +Recursive types necessarily include smart pointers, even when you could normally match through them. +For example, in a proc-macro I worked on to support restricted variadic generics, I wanted to match "fold expressions", which take the form `( ...)`, so I would need to match against `Expr::Paren(ParenExpr{expr: Expr::Binary(ExprBinary{ left, op, right: Expr::Verbaitum(t), ..}), ..})`. However, this is currently not possible, and required nested matches. +This generalizes to any case where you need to check some pattern, but hit a deref boundery. + + +## Prioritization + +I do not believe this fits into any of the listed priorities. +It may be considered "Targeted ergonomic wins and extensions", however, I believe it is a larger than is intended for the category. + +## Links and related work + +This has been discussed on the Rust Internals Forum at , +as well as on zulip at . + +A tracking document of all currently discussed questions and potential answers can be found here . + +Prior discussions raised on the IRLO thread: +* https://github.com/rust-lang/rfcs/pull/462 +* https://github.com/rust-lang/rfcs/issues/2099 +* https://github.com/rust-lang/rfcs/blob/master/text/0809-box-and-in-for-stdlib.md + +## Initial people involved + +I would be involved initially, as well as Nadreiril on zulip. +I would be open to anyone who wished to helping with it. From 47a40b0698077c6e5e8893c8c7dfe79e23eb89e6 Mon Sep 17 00:00:00 2001 From: Connor Horman Date: Thu, 28 Jan 2021 14:47:13 -0500 Subject: [PATCH 2/6] Update deref-patterns.md --- projects/deref-patterns.md | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/projects/deref-patterns.md b/projects/deref-patterns.md index d41faf8..50fb01a 100644 --- a/projects/deref-patterns.md +++ b/projects/deref-patterns.md @@ -7,10 +7,10 @@ Allow pattern matching through types that impl `Deref` or `DerefMut`. Currently in rust, matching is blocked by bounderies like smart pointers, containers, and some wrappers. To solve this problem you would need to either use if let guards (unstable), or nested match/if-let. The former is limited to one such level, and the latter can become excessive for deeply nested types. -To solve this, I propose that "deref patterns" be added, to allow for such matching to be performed. +To solve this, it is proposed propose that "deref patterns" be added, to allow for such matching to be performed. An exception to the above problem, is that `Box` can be matched with `feature(box_patterns)`. -However, this is magic behaviour of box, and I am not a fan of this kind of magic. +However, this is magic behaviour of box, and a goal of this project is to remove that magic. The proposed solution has a number of unanswered questions, including the syntax for patterns, whether or not to limit to standard library types, and how to allow exhaustive patterns soundly if not limited to standard library types. @@ -19,14 +19,13 @@ The proposed solution has a number of unanswered questions, including the syntax ## Motivation, use-cases, and solution sketches Recursive types necessarily include smart pointers, even when you could normally match through them. -For example, in a proc-macro I worked on to support restricted variadic generics, I wanted to match "fold expressions", which take the form `( ...)`, so I would need to match against `Expr::Paren(ParenExpr{expr: Expr::Binary(ExprBinary{ left, op, right: Expr::Verbaitum(t), ..}), ..})`. However, this is currently not possible, and required nested matches. +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 `( ...)`. With deref patterns, this could be implemented using `Expr::Paren(ParenExpr{expr: Expr::Binary(ExprBinary{ left, op, right: Expr::Verbaitum(t), ..}), ..})`. However, this is currently not possible, and required nested matches. This generalizes to any case where you need to check some pattern, but hit a deref boundery. ## Prioritization -I do not believe this fits into any of the listed priorities. -It may be considered "Targeted ergonomic wins and extensions", however, I believe it is a larger than is intended for the category. +This likely does not fit into any of the listed priorities, though it may be considered "Targeted ergonomic wins and extensions". ## Links and related work @@ -42,5 +41,5 @@ Prior discussions raised on the IRLO thread: ## Initial people involved -I would be involved initially, as well as Nadreiril on zulip. -I would be open to anyone who wished to helping with it. +Initially, Connor Horman and Nadriel on zulip would be involved + From 13cde7c7138d401d6ca24db1f9df2ab603689d79 Mon Sep 17 00:00:00 2001 From: Connor Horman Date: Tue, 2 Feb 2021 14:42:36 -0500 Subject: [PATCH 3/6] Update projects/deref-patterns.md Co-authored-by: Josh Triplett --- projects/deref-patterns.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/projects/deref-patterns.md b/projects/deref-patterns.md index 50fb01a..84d4209 100644 --- a/projects/deref-patterns.md +++ b/projects/deref-patterns.md @@ -19,7 +19,7 @@ The proposed solution has a number of unanswered questions, including the syntax ## Motivation, use-cases, and solution sketches Recursive types necessarily include smart pointers, even when you could normally match through them. -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 `( ...)`. With deref patterns, this could be implemented using `Expr::Paren(ParenExpr{expr: Expr::Binary(ExprBinary{ left, op, right: Expr::Verbaitum(t), ..}), ..})`. However, this is currently not possible, and required nested matches. +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 `( ...)`. 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. This generalizes to any case where you need to check some pattern, but hit a deref boundery. @@ -42,4 +42,3 @@ Prior discussions raised on the IRLO thread: ## Initial people involved Initially, Connor Horman and Nadriel on zulip would be involved - From 29220ab774d740572e24fac673c4a6097db3630b Mon Sep 17 00:00:00 2001 From: Connor Horman Date: Tue, 2 Feb 2021 15:01:18 -0500 Subject: [PATCH 4/6] Update deref-patterns.md --- projects/deref-patterns.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/projects/deref-patterns.md b/projects/deref-patterns.md index 84d4209..e2c8353 100644 --- a/projects/deref-patterns.md +++ b/projects/deref-patterns.md @@ -10,11 +10,23 @@ The former is limited to one such level, and the latter can become excessive for To solve this, it is proposed propose that "deref patterns" be added, to allow for such matching to be performed. An exception to the above problem, is that `Box` can be matched with `feature(box_patterns)`. -However, this is magic behaviour of box, and a goal of this project is to remove that magic. +However, this is magic behaviour of box, and a goal of this project is to remove or reduce that magic. The proposed solution has a number of unanswered questions, including the syntax for patterns, whether or not to limit to standard library types, and how to allow exhaustive patterns soundly if not limited to standard library types. +### Exhaustive Patterns and Soundness + +One current issue with the proposed deref patterns is that if applied generally to any type that implements `Deref`, +it cannot soundly permit exhaustive pattern matching, as a malicious `Deref` impl could return a different value each time. +An trivial example would be `Deref` impl that returns a static reference to an enum value that is chosen randomly +There are currently 3 different possible solutions: +* Do not treat deref patterns as exhausitve +* Restrict deref patterns to (possibly a subset of) standard library types +* Expose an unsafe lang item trait called `DerefPure`, and restrict deref patterns to implementors of that trait + +Part of the Project Group would be to evaluate the viability of each solution, and any other reasonable solutions which may come up. + ## Motivation, use-cases, and solution sketches @@ -23,6 +35,7 @@ For example, in a work in progress proc-macro to support restricted variadic gen This generalizes to any case where you need to check some pattern, but hit a deref boundery. + ## Prioritization This likely does not fit into any of the listed priorities, though it may be considered "Targeted ergonomic wins and extensions". From b172d0af2998937f13bd037192f1f4f8f04ca335 Mon Sep 17 00:00:00 2001 From: Connor Horman Date: Tue, 23 Feb 2021 12:00:38 -0500 Subject: [PATCH 5/6] Update Charter to reflect discussions with lang-team --- projects/deref-patterns.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/deref-patterns.md b/projects/deref-patterns.md index e2c8353..aff025f 100644 --- a/projects/deref-patterns.md +++ b/projects/deref-patterns.md @@ -25,7 +25,7 @@ There are currently 3 different possible solutions: * Restrict deref patterns to (possibly a subset of) standard library types * Expose an unsafe lang item trait called `DerefPure`, and restrict deref patterns to implementors of that trait -Part of the Project Group would be to evaluate the viability of each solution, and any other reasonable solutions which may come up. +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 subset that deref patterns can be applied to. ## Motivation, use-cases, and solution sketches From b045ee37d966a22e06bfbf2d5115e3f52b813e28 Mon Sep 17 00:00:00 2001 From: Connor Horman Date: Tue, 23 Feb 2021 13:04:25 -0500 Subject: [PATCH 6/6] Update deref-patterns.md --- projects/deref-patterns.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/deref-patterns.md b/projects/deref-patterns.md index aff025f..3685932 100644 --- a/projects/deref-patterns.md +++ b/projects/deref-patterns.md @@ -25,7 +25,7 @@ There are currently 3 different possible solutions: * Restrict deref patterns to (possibly a subset of) standard library types * Expose an unsafe lang item trait called `DerefPure`, and restrict deref patterns to implementors of that trait -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 subset that deref patterns can be applied to. +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. ## Motivation, use-cases, and solution sketches