Rollup merge of #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: #87121 r? ``@Nadrieril``
This commit is contained in:
commit
c8a9095f0f
33 changed files with 964 additions and 190 deletions
|
|
@ -6,6 +6,8 @@ The tracking issue for this feature is: [#29641]
|
|||
|
||||
------------------------
|
||||
|
||||
> **Note**: This feature will be superseded by [`deref_patterns`] in the future.
|
||||
|
||||
Box patterns let you match on `Box<T>`s:
|
||||
|
||||
|
||||
|
|
@ -28,3 +30,5 @@ fn main() {
|
|||
}
|
||||
}
|
||||
```
|
||||
|
||||
[`deref_patterns`]: ./deref-patterns.md
|
||||
|
|
|
|||
|
|
@ -0,0 +1,57 @@
|
|||
# `deref_patterns`
|
||||
|
||||
The tracking issue for this feature is: [#87121]
|
||||
|
||||
[#87121]: https://github.com/rust-lang/rust/issues/87121
|
||||
|
||||
------------------------
|
||||
|
||||
> **Note**: This feature is incomplete. In the future, it is meant to supersede
|
||||
> [`box_patterns`](./box-patterns.md) and [`string_deref_patterns`](./string-deref-patterns.md).
|
||||
|
||||
This feature permits pattern matching on [smart pointers in the standard library] through their
|
||||
`Deref` target types, either implicitly or with explicit `deref!(_)` patterns (the syntax of which
|
||||
is currently a placeholder).
|
||||
|
||||
```rust
|
||||
#![feature(deref_patterns)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
let mut v = vec![Box::new(Some(0))];
|
||||
|
||||
// Implicit dereferences are inserted when a pattern can match against the
|
||||
// result of repeatedly dereferencing but can't match against a smart
|
||||
// pointer itself. This works alongside match ergonomics for references.
|
||||
if let [Some(x)] = &mut v {
|
||||
*x += 1;
|
||||
}
|
||||
|
||||
// Explicit `deref!(_)` patterns may instead be used when finer control is
|
||||
// needed, e.g. to dereference only a single smart pointer, or to bind the
|
||||
// the result of dereferencing to a variable.
|
||||
if let deref!([deref!(opt_x @ Some(1))]) = &mut v {
|
||||
opt_x.as_mut().map(|x| *x += 1);
|
||||
}
|
||||
|
||||
assert_eq!(v, [Box::new(Some(2))]);
|
||||
```
|
||||
|
||||
Without this feature, it may be necessary to introduce temporaries to represent dereferenced places
|
||||
when matching on nested structures:
|
||||
|
||||
```rust
|
||||
let mut v = vec![Box::new(Some(0))];
|
||||
if let [b] = &mut *v {
|
||||
if let Some(x) = &mut **b {
|
||||
*x += 1;
|
||||
}
|
||||
}
|
||||
if let [b] = &mut *v {
|
||||
if let opt_x @ Some(1) = &mut **b {
|
||||
opt_x.as_mut().map(|x| *x += 1);
|
||||
}
|
||||
}
|
||||
assert_eq!(v, [Box::new(Some(2))]);
|
||||
```
|
||||
|
||||
[smart pointers in the standard library]: https://doc.rust-lang.org/std/ops/trait.DerefPure.html#implementors
|
||||
|
|
@ -6,6 +6,8 @@ The tracking issue for this feature is: [#87121]
|
|||
|
||||
------------------------
|
||||
|
||||
> **Note**: This feature will be superseded by [`deref_patterns`] in the future.
|
||||
|
||||
This feature permits pattern matching `String` to `&str` through [its `Deref` implementation].
|
||||
|
||||
```rust
|
||||
|
|
@ -42,4 +44,5 @@ pub fn is_it_the_answer(value: Value) -> bool {
|
|||
}
|
||||
```
|
||||
|
||||
[`deref_patterns`]: ./deref-patterns.md
|
||||
[its `Deref` implementation]: https://doc.rust-lang.org/std/string/struct.String.html#impl-Deref-for-String
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue