Skip to content

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

Open
1 of 6 tasks
nrc opened this issue Jul 14, 2021 · 66 comments
Open
1 of 6 tasks

Tracking issue: deref patterns #87121

nrc opened this issue Jul 14, 2021 · 66 comments
Labels
A-patterns Relating to patterns and pattern matching C-tracking-issue Category: An issue tracking the progress of sth. like the implementation of an RFC F-deref_patterns `#![feature(deref_patterns)]` needs-rfc This change is large or controversial enough that it should have an RFC accepted before doing it. S-tracking-design-concerns Status: There are blocking design concerns. T-lang Relevant to the language team, which will review and decide on the PR/issue.

Comments

@nrc
Copy link
Member

nrc commented Jul 14, 2021

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.

  • Supported std types: Box, Rc, Arc, Vec, String, Cow, Pin, ManuallyDrop, Ref, RefMut.
  • Unstable types that would be eligible : ThinBox, UniqueRc, LazyCell, LazyLock,

There is also a feature gate just for matching string literals on Strings, under #[feature(string_deref_patterns)].

Unresolved Questions

None at this stage

Implementation history

@nrc nrc added T-lang Relevant to the language team, which will review and decide on the PR/issue. C-tracking-issue Category: An issue tracking the progress of sth. like the implementation of an RFC A-patterns Relating to patterns and pattern matching labels Jul 14, 2021
@nrc
Copy link
Member Author

nrc commented Jul 16, 2021

@roxelo or @matthewjasper would you be able to mentor @chorman0773 on implementing the compiler parts of this please?

@roxelo
Copy link
Member

roxelo commented Jul 19, 2021

@nrc I would not consider myself an expert on the pattern matching code but I can try to help mentor...

@AlbertMarashi
Copy link

AlbertMarashi commented Feb 4, 2022

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!()
    }
}

@chorman0773
Copy link
Contributor

chorman0773 commented Feb 4, 2022 via email

@AlbertMarashi
Copy link

@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.

@rdrpenguin04
Copy link

Just bonked my head into this again; how can I help?

@joshtriplett joshtriplett added S-tracking-design-concerns Status: There are blocking design concerns. needs-rfc This change is large or controversial enough that it should have an RFC accepted before doing it. labels Jul 27, 2022
@safinaskar
Copy link
Contributor

@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

Manishearth added a commit to Manishearth/rust that referenced this issue Nov 16, 2022
…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
bors added a commit to rust-lang-ci/rust that referenced this issue Nov 20, 2022
… 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
flip1995 pushed a commit to flip1995/rust that referenced this issue Nov 21, 2022
… 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
Aaron1011 pushed a commit to Aaron1011/rust that referenced this issue Jan 6, 2023
… 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
@tgross35
Copy link
Contributor

tgross35 commented Jan 22, 2023

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 Deref

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 & or a * needed - that's not yet decided. Super elegant!

@simensgreen
Copy link

simensgreen commented Feb 2, 2023

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?
The compiler somehow correlates

*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.

@tgross35
Copy link
Contributor

tgross35 commented Feb 3, 2023

@simensgreen the trait isn't really an issue at this point, since Deref/DerefMut already gives the information needed (possibly with the marker trait DerefPure that has been discussed a few places). I think at this point, the goal is to start out supporting only builtin types (&str/String, &T/Vec, &T/Box, Rc, Arc).

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

@tgross35
Copy link
Contributor

tgross35 commented Feb 3, 2023

@nrc would you maybe want to update this tracking issue to point to relevant per-type implementations? Probably just:

  • String -> &str: string_deref_patterns implementation Minimal implementation of implicit deref patterns for Strings #98914 (stabilization not started)
  • Box<T> -> &T: box_deref_patterns (not started)
  • Rc<T> -> &T, Arc<T> -> &T: rc_deref_patterns (not started)
  • Vec<T> -> &[T]: slice_deref_patterns (not started)
  • impl DerefPure<Target = U> -> &U: (further discussion needed)

Assuming the goal is to chunk this huge project up into bits that could be stabilized individually.

@simensgreen
Copy link

@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 Mutex. Deref does not have enough information to make a match

@tgross35
Copy link
Contributor

tgross35 commented Feb 7, 2023

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 MutexGuard, which does Deref to &T.

Also, to quote zulip

doing it in general faces some thorny issues around speccing what happens when the deref has side effects, since we want to be able to optimize matches in ways that may not preserve how many deref calls are made

This would be the reason for DerefPure that's come up a few times, an (unsafe?) marker trait to specify a special case of Deref that has no side effects (which is already the case for much of the Deref use in std, there's just no way to express that)

@RalfJung
Copy link
Member

This would be the reason for DerefPure that's come up a few times, an (unsafe?) marker trait to specify a special case of Deref that has no side effects (which is already the case for much of the Deref use in std, there's just no way to express that)

How exactly would this interact with our usual safety requirements / UB? Saying "it is UB to impl DerefPure on a non-pure impl Deref" is quite problematic as this would be UB which cannot be checked by a sanitizer such as Miri. Ideally we'd end up in a situation where a wrong DerefPure can lead to surprising behavior, but is not in and of itself UB.

Cc @rust-lang/opsem

@CAD97
Copy link
Contributor

CAD97 commented Feb 28, 2023

I would initially expect it to behave like any other unsafe trait implementation: it gives downstream code permission to rely on the guaranteed properties, but doesn't result in UB until downstream code relies on that property to maintain soundness. Or IOW, library UB.

I think it probably does need to be unsafe, though, because it's not just about collapsing multiple calls into one, but also introducing calls where they wouldn't otherwise exist by strictly inorder trial evaluation of match arms. Since this makes otherwise dead code live, that feels unsafe, but it also can be justified as just safe misbehavior.

"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-ref and by-ref mut binding modes, which while not technically unsafe (it's safe to do &*&mut *it to use DerefMut to get &T) also feels like it should be an unsafe guarantee that both are equivalent and interchangable places modulo provenance.

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 DerefPure's purity promise is utilized anywhere outside of deref patterns. E.g. it could potentially be used to enable borrow splitting, either by caching the place evaluation and/or not invalidating previously split borrows, although the latter means such place evaluation can't use typical reborrowing references.

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 DerefPure should provide before it can properly be discussed whether that requires it to be unsafe.

@AlbertMarashi
Copy link

AlbertMarashi commented Aug 2, 2024

#![feature(string_deref_patterns)] doesn't seem to work with rust-analyzer. Any workarounds?

@Nadrieril
Copy link
Member

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.

workingjubilee added a commit to workingjubilee/rustc that referenced this issue Feb 16, 2025
…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
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Feb 17, 2025
…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
rust-timer added a commit to rust-lang-ci/rust that referenced this issue Feb 17, 2025
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
github-merge-queue bot pushed a commit to rust-lang/rust-analyzer that referenced this issue Feb 24, 2025
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
BoxyUwU pushed a commit to BoxyUwU/rustc-dev-guide that referenced this issue Feb 25, 2025
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
github-actions bot pushed a commit to tautschnig/verify-rust-std that referenced this issue Mar 11, 2025
…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
github-actions bot pushed a commit to tautschnig/verify-rust-std that referenced this issue Mar 11, 2025
…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
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Apr 17, 2025
…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`
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Apr 17, 2025
…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`
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Apr 18, 2025
…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``
rust-timer added a commit to rust-lang-ci/rust that referenced this issue Apr 18, 2025
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``
flip1995 pushed a commit to flip1995/rust that referenced this issue Apr 22, 2025
…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``
Zalathar added a commit to Zalathar/rust that referenced this issue Apr 24, 2025
`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.
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Apr 24, 2025
`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.
rust-timer added a commit to rust-lang-ci/rust that referenced this issue Apr 24, 2025
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-patterns Relating to patterns and pattern matching C-tracking-issue Category: An issue tracking the progress of sth. like the implementation of an RFC F-deref_patterns `#![feature(deref_patterns)]` needs-rfc This change is large or controversial enough that it should have an RFC accepted before doing it. S-tracking-design-concerns Status: There are blocking design concerns. T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests