-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Tracking issue: deref patterns #87121
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
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 |
|
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. |
…Nadrieril Restrict DerefPure for Cow<T> impl to T = impl Clone, [impl Clone], str. Fixes rust-lang#136046 `feature(deref_patterns)` tracking issue: rust-lang#87121 `Cow<'_, T>` should only implement `DerefPure` if its `Deref` impl is pure, which requires `<T::Owned as Borrow<T>>::borrow` to be pure. This PR restricts `impl DerefPure for Cow<'_, T>` to `T: Sized + Clone`, `T = [U: Clone]`, and `T = str` (for all of whom `<T::Owned as Borrow<T>>::borrow` is implemented in the stdlib and is pure). cc `@Nadrieril` ------ An alternate approach would be to introduce a new `unsafe trait BorrowPure<T>` analogous to `DerefPure` that could be implemented for `T: Sized`, `&T`, `&mut T`, `String`, `Vec`, `Box`, `PathBuf`, `OsString`, etc. rust-lang/rust@master...zachs18:borrow-pure-trait
…Nadrieril Restrict DerefPure for Cow<T> impl to T = impl Clone, [impl Clone], str. Fixes rust-lang#136046 `feature(deref_patterns)` tracking issue: rust-lang#87121 `Cow<'_, T>` should only implement `DerefPure` if its `Deref` impl is pure, which requires `<T::Owned as Borrow<T>>::borrow` to be pure. This PR restricts `impl DerefPure for Cow<'_, T>` to `T: Sized + Clone`, `T = [U: Clone]`, and `T = str` (for all of whom `<T::Owned as Borrow<T>>::borrow` is implemented in the stdlib and is pure). cc ``@Nadrieril`` ------ An alternate approach would be to introduce a new `unsafe trait BorrowPure<T>` analogous to `DerefPure` that could be implemented for `T: Sized`, `&T`, `&mut T`, `String`, `Vec`, `Box`, `PathBuf`, `OsString`, etc. rust-lang/rust@master...zachs18:borrow-pure-trait
Rollup merge of rust-lang#137105 - zachs18:cow-derefpure-restrict, r=Nadrieril Restrict DerefPure for Cow<T> impl to T = impl Clone, [impl Clone], str. Fixes rust-lang#136046 `feature(deref_patterns)` tracking issue: rust-lang#87121 `Cow<'_, T>` should only implement `DerefPure` if its `Deref` impl is pure, which requires `<T::Owned as Borrow<T>>::borrow` to be pure. This PR restricts `impl DerefPure for Cow<'_, T>` to `T: Sized + Clone`, `T = [U: Clone]`, and `T = str` (for all of whom `<T::Owned as Borrow<T>>::borrow` is implemented in the stdlib and is pure). cc ``@Nadrieril`` ------ An alternate approach would be to introduce a new `unsafe trait BorrowPure<T>` analogous to `DerefPure` that could be implemented for `T: Sized`, `&T`, `&mut T`, `String`, `Vec`, `Box`, `PathBuf`, `OsString`, etc. rust-lang/rust@master...zachs18:borrow-pure-trait
Restrict DerefPure for Cow<T> impl to T = impl Clone, [impl Clone], str. Fixes #136046 `feature(deref_patterns)` tracking issue: rust-lang/rust#87121 `Cow<'_, T>` should only implement `DerefPure` if its `Deref` impl is pure, which requires `<T::Owned as Borrow<T>>::borrow` to be pure. This PR restricts `impl DerefPure for Cow<'_, T>` to `T: Sized + Clone`, `T = [U: Clone]`, and `T = str` (for all of whom `<T::Owned as Borrow<T>>::borrow` is implemented in the stdlib and is pure). cc ``@Nadrieril`` ------ An alternate approach would be to introduce a new `unsafe trait BorrowPure<T>` analogous to `DerefPure` that could be implemented for `T: Sized`, `&T`, `&mut T`, `String`, `Vec`, `Box`, `PathBuf`, `OsString`, etc. rust-lang/rust@master...zachs18:borrow-pure-trait
Restrict DerefPure for Cow<T> impl to T = impl Clone, [impl Clone], str. Fixes #136046 `feature(deref_patterns)` tracking issue: rust-lang/rust#87121 `Cow<'_, T>` should only implement `DerefPure` if its `Deref` impl is pure, which requires `<T::Owned as Borrow<T>>::borrow` to be pure. This PR restricts `impl DerefPure for Cow<'_, T>` to `T: Sized + Clone`, `T = [U: Clone]`, and `T = str` (for all of whom `<T::Owned as Borrow<T>>::borrow` is implemented in the stdlib and is pure). cc ``@Nadrieril`` ------ An alternate approach would be to introduce a new `unsafe trait BorrowPure<T>` analogous to `DerefPure` that could be implemented for `T: Sized`, `&T`, `&mut T`, `String`, `Vec`, `Box`, `PathBuf`, `OsString`, etc. rust-lang/rust@master...zachs18:borrow-pure-trait
…Nadrieril Restrict DerefPure for Cow<T> impl to T = impl Clone, [impl Clone], str. Fixes rust-lang#136046 `feature(deref_patterns)` tracking issue: rust-lang#87121 `Cow<'_, T>` should only implement `DerefPure` if its `Deref` impl is pure, which requires `<T::Owned as Borrow<T>>::borrow` to be pure. This PR restricts `impl DerefPure for Cow<'_, T>` to `T: Sized + Clone`, `T = [U: Clone]`, and `T = str` (for all of whom `<T::Owned as Borrow<T>>::borrow` is implemented in the stdlib and is pure). cc ``@Nadrieril`` ------ An alternate approach would be to introduce a new `unsafe trait BorrowPure<T>` analogous to `DerefPure` that could be implemented for `T: Sized`, `&T`, `&mut T`, `String`, `Vec`, `Box`, `PathBuf`, `OsString`, etc. rust-lang/rust@master...zachs18:borrow-pure-trait
…Nadrieril Restrict DerefPure for Cow<T> impl to T = impl Clone, [impl Clone], str. Fixes rust-lang#136046 `feature(deref_patterns)` tracking issue: rust-lang#87121 `Cow<'_, T>` should only implement `DerefPure` if its `Deref` impl is pure, which requires `<T::Owned as Borrow<T>>::borrow` to be pure. This PR restricts `impl DerefPure for Cow<'_, T>` to `T: Sized + Clone`, `T = [U: Clone]`, and `T = str` (for all of whom `<T::Owned as Borrow<T>>::borrow` is implemented in the stdlib and is pure). cc ``@Nadrieril`` ------ An alternate approach would be to introduce a new `unsafe trait BorrowPure<T>` analogous to `DerefPure` that could be implemented for `T: Sized`, `&T`, `&mut T`, `String`, `Vec`, `Box`, `PathBuf`, `OsString`, etc. rust-lang/rust@master...zachs18:borrow-pure-trait
…Nadrieril deref patterns: implement implicit deref patterns This implements implicit deref patterns (per https://hackmd.io/4qDDMcvyQ-GDB089IPcHGg#Implicit-deref-patterns) and adds tests and an unstable book chapter. Best reviewed commit-by-commit. Overall there's a lot of additions, but a lot of that is tests, documentation, and simple(?) refactoring. Tracking issue: rust-lang#87121 r? `@Nadrieril`
…Nadrieril deref patterns: implement implicit deref patterns This implements implicit deref patterns (per https://hackmd.io/4qDDMcvyQ-GDB089IPcHGg#Implicit-deref-patterns) and adds tests and an unstable book chapter. Best reviewed commit-by-commit. Overall there's a lot of additions, but a lot of that is tests, documentation, and simple(?) refactoring. Tracking issue: rust-lang#87121 r? `@Nadrieril`
…Nadrieril deref patterns: implement implicit deref patterns This implements implicit deref patterns (per https://hackmd.io/4qDDMcvyQ-GDB089IPcHGg#Implicit-deref-patterns) and adds tests and an unstable book chapter. Best reviewed commit-by-commit. Overall there's a lot of additions, but a lot of that is tests, documentation, and simple(?) refactoring. Tracking issue: rust-lang#87121 r? ``@Nadrieril``
Rollup merge of rust-lang#138528 - dianne:implicit-deref-patterns, r=Nadrieril deref patterns: implement implicit deref patterns This implements implicit deref patterns (per https://hackmd.io/4qDDMcvyQ-GDB089IPcHGg#Implicit-deref-patterns) and adds tests and an unstable book chapter. Best reviewed commit-by-commit. Overall there's a lot of additions, but a lot of that is tests, documentation, and simple(?) refactoring. Tracking issue: rust-lang#87121 r? ``@Nadrieril``
…Nadrieril deref patterns: implement implicit deref patterns This implements implicit deref patterns (per https://hackmd.io/4qDDMcvyQ-GDB089IPcHGg#Implicit-deref-patterns) and adds tests and an unstable book chapter. Best reviewed commit-by-commit. Overall there's a lot of additions, but a lot of that is tests, documentation, and simple(?) refactoring. Tracking issue: rust-lang#87121 r? ``@Nadrieril``
`deref_patterns`: support string and byte string literals in explicit `deref!("...")` patterns When `deref_patterns` is enabled, this allows string literal patterns to be used where `str` is expected and byte string literal patterns to be used where `[u8]` or `[u8; N]` is expected. This lets them be used in explicit `deref!("...")` patterns to match on `String`, `Box<str>`, `Vec<u8>`, `Box<[u8;N]>`, etc. (as well as to match on slices and arrays obtained through other means). Implementation-wise, this follows up on rust-lang#138992: similar to how byte string literals matching on `&[u8]` is implemented, this changes the type of the patterns as determined by HIR typeck, which informs const-to-pat on how to translate them to THIR (though strings needed a bit of extra work since we need references to call `<str as PartialEq>::eq` in the MIR lowering for string equality tests). This PR does not add support for implicit deref pattern syntax (e.g. `"..."` matching on `String`, as `string_deref_patterns` allows). I have that implemented locally, but I'm saving it for a follow-up PR[^1]. This also does not add support for using named or associated constants of type `&str` where `str` is expected (nor likewise with named byte string constants). It'd be possible to add that if there's an appetite for it, but I figure it's simplest to start with literals. This is gated by the `deref_patterns` feature since it's motivated by deref patterns. That said, its impact reaches outside of deref patterns; it may warrant a separate experiment and feature gate, particularly factoring in the follow-up[^1]. Even without deref patterns, I think there's probably motivation for these changes. The update to the unstable book added by this will conflict with rust-lang#140022, so they shouldn't be merged at the same time. Tracking issue for deref patterns: rust-lang#87121 r? `@oli-obk` cc `@Nadrieril` [^1]: The piece missing from this PR to support implicit deref pattern syntax is to allow string literal patterns to implicitly dereference their scrutinees before matching (see rust-lang#44849). As a consequence, it also makes examples like the one in that issue work (though it's still gated by `deref_patterns`). I can provide more information on how I've implemented it or open a draft if it'd help in reviewing this PR.
`deref_patterns`: support string and byte string literals in explicit `deref!("...")` patterns When `deref_patterns` is enabled, this allows string literal patterns to be used where `str` is expected and byte string literal patterns to be used where `[u8]` or `[u8; N]` is expected. This lets them be used in explicit `deref!("...")` patterns to match on `String`, `Box<str>`, `Vec<u8>`, `Box<[u8;N]>`, etc. (as well as to match on slices and arrays obtained through other means). Implementation-wise, this follows up on rust-lang#138992: similar to how byte string literals matching on `&[u8]` is implemented, this changes the type of the patterns as determined by HIR typeck, which informs const-to-pat on how to translate them to THIR (though strings needed a bit of extra work since we need references to call `<str as PartialEq>::eq` in the MIR lowering for string equality tests). This PR does not add support for implicit deref pattern syntax (e.g. `"..."` matching on `String`, as `string_deref_patterns` allows). I have that implemented locally, but I'm saving it for a follow-up PR[^1]. This also does not add support for using named or associated constants of type `&str` where `str` is expected (nor likewise with named byte string constants). It'd be possible to add that if there's an appetite for it, but I figure it's simplest to start with literals. This is gated by the `deref_patterns` feature since it's motivated by deref patterns. That said, its impact reaches outside of deref patterns; it may warrant a separate experiment and feature gate, particularly factoring in the follow-up[^1]. Even without deref patterns, I think there's probably motivation for these changes. The update to the unstable book added by this will conflict with rust-lang#140022, so they shouldn't be merged at the same time. Tracking issue for deref patterns: rust-lang#87121 r? ``@oli-obk`` cc ``@Nadrieril`` [^1]: The piece missing from this PR to support implicit deref pattern syntax is to allow string literal patterns to implicitly dereference their scrutinees before matching (see rust-lang#44849). As a consequence, it also makes examples like the one in that issue work (though it's still gated by `deref_patterns`). I can provide more information on how I've implemented it or open a draft if it'd help in reviewing this PR.
Rollup merge of rust-lang#140028 - dianne:lit-deref-pats-p1, r=oli-obk `deref_patterns`: support string and byte string literals in explicit `deref!("...")` patterns When `deref_patterns` is enabled, this allows string literal patterns to be used where `str` is expected and byte string literal patterns to be used where `[u8]` or `[u8; N]` is expected. This lets them be used in explicit `deref!("...")` patterns to match on `String`, `Box<str>`, `Vec<u8>`, `Box<[u8;N]>`, etc. (as well as to match on slices and arrays obtained through other means). Implementation-wise, this follows up on rust-lang#138992: similar to how byte string literals matching on `&[u8]` is implemented, this changes the type of the patterns as determined by HIR typeck, which informs const-to-pat on how to translate them to THIR (though strings needed a bit of extra work since we need references to call `<str as PartialEq>::eq` in the MIR lowering for string equality tests). This PR does not add support for implicit deref pattern syntax (e.g. `"..."` matching on `String`, as `string_deref_patterns` allows). I have that implemented locally, but I'm saving it for a follow-up PR[^1]. This also does not add support for using named or associated constants of type `&str` where `str` is expected (nor likewise with named byte string constants). It'd be possible to add that if there's an appetite for it, but I figure it's simplest to start with literals. This is gated by the `deref_patterns` feature since it's motivated by deref patterns. That said, its impact reaches outside of deref patterns; it may warrant a separate experiment and feature gate, particularly factoring in the follow-up[^1]. Even without deref patterns, I think there's probably motivation for these changes. The update to the unstable book added by this will conflict with rust-lang#140022, so they shouldn't be merged at the same time. Tracking issue for deref patterns: rust-lang#87121 r? ``@oli-obk`` cc ``@Nadrieril`` [^1]: The piece missing from this PR to support implicit deref pattern syntax is to allow string literal patterns to implicitly dereference their scrutinees before matching (see rust-lang#44849). As a consequence, it also makes examples like the one in that issue work (though it's still gated by `deref_patterns`). I can provide more information on how I've implemented it or open a draft if it'd help in reviewing this PR.
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: