-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tracking issue: deref patterns #87121
Comments
@roxelo or @matthewjasper would you be able to mentor @chorman0773 on implementing the compiler parts of this please? |
@nrc I would not consider myself an expert on the pattern matching code but I can try to help mentor... |
I have this code, it does not compile. I am trying to match a
but there's no good way to match #![feature(box_patterns)]
struct Type {
pub name: Box<str>,
pub generics: Option<Vec<Type>>
}
fn main(){
let kind = Type {
name: "User".into(),
generics: Some(Vec::new())
};
match kind {
Type {
name: box "User",
generics
} => {}
_ => unimplemented!()
}
} |
This would be should get solved by deref patterns.
…On Fri, Feb 4, 2022 at 05:39 Albert Marashi ***@***.***> wrote:
I have this code, it does not compile. I am trying to match a Box<str>
inside of a pattern, but the error is: expected str, found '&str' but
there's no good way to match Box<str> in a deeply nested pattern...
#![feature(box_patterns)]struct Type {
pub name: Box<str>,
pub generics: Option<Vec<Type>>
}
fn main(){
let kind = Type {
name: "User".into(),
generics: Some(Vec::new())
};
match kind {
Type {
name: box "User",
generics
} => {}
_ => unimplemented!()
}
}
—
Reply to this email directly, view it on GitHub
<#87121 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ABGLD27M7YLN2UD7MELBLH3UZOUG5ANCNFSM5AKRWKLA>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
@chorman0773 anything I can do to help move this forward? I'd really love to see this feature in rust, it would be insanely useful for deep matching of things like ASTs. |
Just bonked my head into this again; how can I help? |
@rdrpenguin04 and everybody else who cannot wait: I made a proc macro crate, which implements deref patterns in stable Rust: https://crates.io/crates/match_deref |
…s, r=compiler-errors Minimal implementation of implicit deref patterns for Strings cc `@compiler-errors` `@BoxyUwU` rust-lang/lang-team#88 rust-lang#87121 ~~I forgot to add a feature gate, will do so in a minute~~ Done
… r=compiler-errors Minimal implementation of implicit deref patterns for Strings cc `@compiler-errors` `@BoxyUwU` rust-lang/lang-team#88 rust-lang#87121 ~~I forgot to add a feature gate, will do so in a minute~~ Done
… r=compiler-errors Minimal implementation of implicit deref patterns for Strings cc `@compiler-errors` `@BoxyUwU` rust-lang/lang-team#88 rust-lang#87121 ~~I forgot to add a feature gate, will do so in a minute~~ Done
… r=compiler-errors Minimal implementation of implicit deref patterns for Strings cc `@compiler-errors` `@BoxyUwU` rust-lang/lang-team#88 rust-lang#87121 ~~I forgot to add a feature gate, will do so in a minute~~ Done
Is anybody involved here able to provide a rough outline or example of what this will look like when stable? I'm imagining this will be something that's automatic for anything that implements if let Some(u8) = Some(Rc::new(10)) { ... }
if let Some("yellow world") = Some(Box::new(String::from("hello world"))) { ... } edit: according to Mario on Zulip, this would be keywordless, maybe with a |
Why can't we make trait Match {
type Target: ?Sized;
fn do_match(&self) -> &Self::Target;
}
trait MatchMut: Match {
fn do_match_mut(&mut self) -> &mut Self::Target;
} how is it done with Deref and Derefmut, respectively? *x
// and
<&XType as Deref>::deref(&x) why not do the same with match? match x {}
// and
<XType as Match>::do_match(&x) This would solve how to match strings, SmartPointers, and other more complex constructs without adding new syntax to the language. |
@simensgreen the trait isn't really an issue at this point, since And I think the blocker at this point is just time/people. Look at #98914 needed just to support strings, it's a pretty big change |
@nrc would you maybe want to update this tracking issue to point to relevant per-type implementations? Probably just:
Assuming the goal is to chunk this huge project up into bits that could be stabilized individually. |
@tgross35 The existence of such a trait will help to implement match not only for standard types, including strings, but also for any arbitrary types, like |
You wouldn't be able to pattern match directly on a Mutex, and that's a good thing because implicitly locking would lead to some very difficult to follow code. However, you could lock it yourself and then pattern match on the Also, to quote zulip
This would be the reason for |
How exactly would this interact with our usual safety requirements / UB? Saying "it is UB to Cc @rust-lang/opsem |
I would initially expect it to behave like any other I think it probably does need to be "I don't say how many times this gets executed" is a pretty textbook example of library instability which can't be validated operationally, although in this case it's as part of the language rather than library. The only guarantee I think the deref impl gets is that it's evaluated at least once if an arm containing it is I also think there might be an element of one deref place evaluation being sufficient for both by- What sanitizers could do is always execute all structurally reachable pattern derefs from any arms, whether that arm is even reachable or not. Randomized sanitizers could also probabilistically vary how many times the derefs get evaluated, including zero times if unnecessary, and many more times than present in patterns. Alternatively, the strong position is to go super strict about pattern derefs being not just pure but also just being composed from place computation primitives; in this case such implementations could even be verified statically to be only composed of such operations. Even if this isn't stated required at a language level, validating such composition dynamically ensures actual purity and as such skipping dynamic validation of spurious (non)evaluation. Then, only partially unrelated, is the question on whether Properly built-in place evaluation has a number of extra differences to overloadable place evaluation (pattern transparency, borrow splitting, "deref move", purity, const), and it needs to be decided how much or how little of that |
@ThePuzzlemaker awesome! @Nadrieril or @CAD97 would be able to give you more details about where exactly to look, but it will touch a lot of the areas that were relevant in making this work for You should also drop by Zulip to coordinate efforts and ask any smaller questions, the relevant stream is here: https://rust-lang.zulipchat.com/#narrow/stream/281601-project-deref-patterns. A reasonable first step is to make any pattern work for a single match for anything that is |
I've realized that I think this is a little out of my ability at the moment 😅, sorry |
Dw, a bunch of us are eager to get this and are slowly making progress |
Would this allow for moving out of boxes? Or only getting a reference of the inner value? It's quite common for interpreters to have a recursive type like enum Expr {
If(Box<Expr>, Box<Expr>, Box<Expr>),
...
} And being able to destructure that by moving out of Box would make code much simpler, eg. match expr {
If(cond, left, right) => { /* Use owned `Expr` values here */ }
} |
I think we want to get something like that eventually, but that's not included in this proposal. The difficulty is from a language design pov: what syntax to use, how/whether to generalize that to other types than Box (which draws in the thorny |
I mean, right now as it stands, |
If this does not allow moving out of boxes, we should be careful to be forward-compatible with eventually allowing moving out of boxes. |
Work on the feature is restarting. I'd like to remind everyone that
especially since the design aspects are contentious. Thank you! See you on zulip for discussions. |
Dear T-lang, the liaison for this initiative (cramertj) has retired from the lang team. Progress is therefore halted until a new liaison is found. I would like to raise this for the next triage meeting so a liaison can be found, if the team still wants this feature to happen. I will be there to answer questions. |
@rustbot labels -I-lang-nominated We discussed this in the lang triage call today. The consensus was that I would pick up the liaisoning here, so please let me know whenever anything is needed to move this along. Thanks to @Nadrieril for pushing this forward; we'll all excited to see the outcome of that. |
…r=compiler-errors deref patterns: bare-bones feature gate and typechecking I am restarting the deref patterns experimentation. This introduces a feature gate under the lang-team [experimental feature](https://github.com/rust-lang/lang-team/blob/master/src/how_to/experiment.md) process, with [`@cramertj` as lang-team liaison](rust-lang/lang-team#88) (it's been a while though, you still ok with this `@cramertj?).` Tracking issue: rust-lang#87121. This is the barest-bones implementation I could think of: - explicit syntax, reusing `box <pat>` because that saves me a ton of work; - use `Deref` as a marker trait (instead of a yet-to-design `DerefPure`); - no support for mutable patterns with `DerefMut` for now; - MIR lowering will come in the next PR. It's the trickiest part. My goal is to let us figure out the MIR lowering part, which might take some work. And hopefully get something working for std types soon. This is in large part salvaged from `@fee1-dead's` rust-lang#119467. r? `@compiler-errors`
…r=compiler-errors deref patterns: bare-bones feature gate and typechecking I am restarting the deref patterns experimentation. This introduces a feature gate under the lang-team [experimental feature](https://github.com/rust-lang/lang-team/blob/master/src/how_to/experiment.md) process, with [``@cramertj`` as lang-team liaison](rust-lang/lang-team#88) (it's been a while though, you still ok with this ``@cramertj?).`` Tracking issue: rust-lang#87121. This is the barest-bones implementation I could think of: - explicit syntax, reusing `box <pat>` because that saves me a ton of work; - use `Deref` as a marker trait (instead of a yet-to-design `DerefPure`); - no support for mutable patterns with `DerefMut` for now; - MIR lowering will come in the next PR. It's the trickiest part. My goal is to let us figure out the MIR lowering part, which might take some work. And hopefully get something working for std types soon. This is in large part salvaged from ``@fee1-dead's`` rust-lang#119467. r? ``@compiler-errors``
…r=compiler-errors deref patterns: bare-bones feature gate and typechecking I am restarting the deref patterns experimentation. This introduces a feature gate under the lang-team [experimental feature](https://github.com/rust-lang/lang-team/blob/master/src/how_to/experiment.md) process, with [```@cramertj``` as lang-team liaison](rust-lang/lang-team#88) (it's been a while though, you still ok with this ```@cramertj?).``` Tracking issue: rust-lang#87121. This is the barest-bones implementation I could think of: - explicit syntax, reusing `box <pat>` because that saves me a ton of work; - use `Deref` as a marker trait (instead of a yet-to-design `DerefPure`); - no support for mutable patterns with `DerefMut` for now; - MIR lowering will come in the next PR. It's the trickiest part. My goal is to let us figure out the MIR lowering part, which might take some work. And hopefully get something working for std types soon. This is in large part salvaged from ```@fee1-dead's``` rust-lang#119467. r? ```@compiler-errors```
…r=compiler-errors deref patterns: bare-bones feature gate and typechecking I am restarting the deref patterns experimentation. This introduces a feature gate under the lang-team [experimental feature](https://github.com/rust-lang/lang-team/blob/master/src/how_to/experiment.md) process, with [````@cramertj```` as lang-team liaison](rust-lang/lang-team#88) (it's been a while though, you still ok with this ````@cramertj?).```` Tracking issue: rust-lang#87121. This is the barest-bones implementation I could think of: - explicit syntax, reusing `box <pat>` because that saves me a ton of work; - use `Deref` as a marker trait (instead of a yet-to-design `DerefPure`); - no support for mutable patterns with `DerefMut` for now; - MIR lowering will come in the next PR. It's the trickiest part. My goal is to let us figure out the MIR lowering part, which might take some work. And hopefully get something working for std types soon. This is in large part salvaged from ````@fee1-dead's```` rust-lang#119467. r? ````@compiler-errors````
Rollup merge of rust-lang#122222 - Nadrieril:deref-pat-feature-gate, r=compiler-errors deref patterns: bare-bones feature gate and typechecking I am restarting the deref patterns experimentation. This introduces a feature gate under the lang-team [experimental feature](https://github.com/rust-lang/lang-team/blob/master/src/how_to/experiment.md) process, with [````@cramertj```` as lang-team liaison](rust-lang/lang-team#88) (it's been a while though, you still ok with this ````@cramertj?).```` Tracking issue: rust-lang#87121. This is the barest-bones implementation I could think of: - explicit syntax, reusing `box <pat>` because that saves me a ton of work; - use `Deref` as a marker trait (instead of a yet-to-design `DerefPure`); - no support for mutable patterns with `DerefMut` for now; - MIR lowering will come in the next PR. It's the trickiest part. My goal is to let us figure out the MIR lowering part, which might take some work. And hopefully get something working for std types soon. This is in large part salvaged from ````@fee1-dead's```` rust-lang#119467. r? ````@compiler-errors````
…ompiler-errors deref patterns: impl `DerefPure` for more std types Context: [deref patterns](rust-lang#87121). The requirements of `DerefPure` aren't precise yet, but these types unambiguously satisfy them. Interestingly, a hypothetical `impl DerefMut for Cow` that does a `Clone` would *not* be eligible for `DerefPure` if we allow mixing deref patterns with normal patterns. If the following is exhaustive then the `DerefMut` would cause UB: ```rust match &mut Cow::Borrowed(&()) { Cow::Owned(_) => ..., // Doesn't match deref!(_x) if false => ..., // Causes the variant to switch to `Owned` Cow::Borrowed(_) => ..., // Doesn't match // We reach unreachable } ```
Rollup merge of rust-lang#123480 - Nadrieril:impl-all-derefpures, r=compiler-errors deref patterns: impl `DerefPure` for more std types Context: [deref patterns](rust-lang#87121). The requirements of `DerefPure` aren't precise yet, but these types unambiguously satisfy them. Interestingly, a hypothetical `impl DerefMut for Cow` that does a `Clone` would *not* be eligible for `DerefPure` if we allow mixing deref patterns with normal patterns. If the following is exhaustive then the `DerefMut` would cause UB: ```rust match &mut Cow::Borrowed(&()) { Cow::Owned(_) => ..., // Doesn't match deref!(_x) if false => ..., // Causes the variant to switch to `Owned` Cow::Borrowed(_) => ..., // Doesn't match // We reach unreachable } ```
|
This is still pretty experimental. To make it work, rust-analyzer would have to update their type-checker to recognize these new patterns. It feels premature at this point of the development of the feature. |
Tracking issue for implementing deref patterns (
#[feature(deref_patterns)]
).deref patterns project group repo
lang team initiative issue
About tracking issues
Tracking issues are used to record the overall progress of implementation.
They are also used as hubs connecting to other relevant issues, e.g., bugs or open design questions.
A tracking issue is however not meant for large scale discussion, questions, or bug reports about a feature.
Instead, open a dedicated issue for the specific matter and add the relevant feature gate label.
Steps
Status
The current implementation uses a placeholder
deref!(<pat>)
syntax and is limited to types in the standard library. See the design proposal document for more details.We limit to types in the standard library using the unstable trait
DerefPure
(#[feature(deref_pure_trait)]
). It is not intended to be stabilized at this stage.Box
,Rc
,Arc
,Vec
,String
,Cow
,Pin
,ManuallyDrop
,Ref
,RefMut
.ThinBox
,UniqueRc
,LazyCell
,LazyLock
,There is also a feature gate just for matching string literals on
String
s, under#[feature(string_deref_patterns)]
.Unresolved Questions
None at this stage
Implementation history
k#deref
#119467DerefMut
andDerefPure
onderef!()
patterns when appropriate #122835DerefPure
for more std types #123480The text was updated successfully, but these errors were encountered: