about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorMatthias Krüger <476013+matthiaskrgr@users.noreply.github.com>2025-04-18 05:16:28 +0200
committerGitHub <noreply@github.com>2025-04-18 05:16:28 +0200
commitc8a9095f0f57f7a482aed4e464ec284e8f98b37b (patch)
tree50b27381572db5ab399fcb83ae2905bf92eb7ad2 /src
parent1f76d219c906f0112bb1872f33aa977164c53fa6 (diff)
parent3b91b7ac57a534bbb1d4f39f679f86040a588903 (diff)
downloadrust-c8a9095f0f57f7a482aed4e464ec284e8f98b37b.tar.gz
rust-c8a9095f0f57f7a482aed4e464ec284e8f98b37b.zip
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``
Diffstat (limited to 'src')
-rw-r--r--src/doc/unstable-book/src/language-features/box-patterns.md4
-rw-r--r--src/doc/unstable-book/src/language-features/deref-patterns.md57
-rw-r--r--src/doc/unstable-book/src/language-features/string-deref-patterns.md3
-rw-r--r--src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs2
4 files changed, 65 insertions, 1 deletions
diff --git a/src/doc/unstable-book/src/language-features/box-patterns.md b/src/doc/unstable-book/src/language-features/box-patterns.md
index a1ac09633b7..c8a15b8477e 100644
--- a/src/doc/unstable-book/src/language-features/box-patterns.md
+++ b/src/doc/unstable-book/src/language-features/box-patterns.md
@@ -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
diff --git a/src/doc/unstable-book/src/language-features/deref-patterns.md b/src/doc/unstable-book/src/language-features/deref-patterns.md
new file mode 100644
index 00000000000..d0102a665b0
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/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
diff --git a/src/doc/unstable-book/src/language-features/string-deref-patterns.md b/src/doc/unstable-book/src/language-features/string-deref-patterns.md
index 3723830751e..366bb15d4ea 100644
--- a/src/doc/unstable-book/src/language-features/string-deref-patterns.md
+++ b/src/doc/unstable-book/src/language-features/string-deref-patterns.md
@@ -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
diff --git a/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs b/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs
index 8f1a1ee76c6..96d3f7196c0 100644
--- a/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs
+++ b/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs
@@ -179,7 +179,7 @@ fn find_first_mismatch(cx: &LateContext<'_>, pat: &Pat<'_>) -> Option<(Span, Mut
         };
         if let Some(adjustments) = cx.typeck_results().pat_adjustments().get(adjust_pat.hir_id) {
             if let [first, ..] = **adjustments {
-                if let ty::Ref(.., mutability) = *first.kind() {
+                if let ty::Ref(.., mutability) = *first.source.kind() {
                     let level = if p.hir_id == pat.hir_id {
                         Level::Top
                     } else {