Skip to content

Commit 76e7d7c

Browse files
committed
Add admonition about pointer vs pointee capturing
There's some surprising nuance to what gets captured when reading the length of a slice with a slice pattern. Let's add an admonition about this.
1 parent 6a6295d commit 76e7d7c

File tree

1 file changed

+28
-0
lines changed

1 file changed

+28
-0
lines changed

src/types/closure.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,34 @@ let _ = &mut *x; // OK: `*x` can be borrow here.
402402
c();
403403
```
404404

405+
> [!NOTE]
406+
> Perhaps surprisingly, even though the length is contained in the (wide) *pointer* to the slice, it is the place of the *pointee* (the slice) that is treated as read and is captured.
407+
>
408+
> ```rust,no_run
409+
> fn f<'l: 's, 's>(x: &'s mut &'l [u8]) -> impl Fn() + 'l {
410+
> // The closure outlives `'l` because it captures `**x`. If
411+
> // instead it captured `*x`, it would not live long enough
412+
> // to satisfy the `impl Fn() + 'l` bound.
413+
> || match *x { // Captures `**x` by `ImmBorrow`.
414+
> &[] => (),
415+
> _ => (),
416+
> }
417+
> }
418+
> ```
419+
>
420+
> In this way, the behavior is consistent with dereferencing to the slice in the scrutinee.
421+
>
422+
> ```rust,no_run
423+
> fn f<'l: 's, 's>(x: &'s mut &'l [u8]) -> impl Fn() + 'l {
424+
> || match **x { // Captures `**x` by `ImmBorrow`.
425+
> [] => (),
426+
> _ => (),
427+
> }
428+
> }
429+
> ```
430+
>
431+
> For details, see [Rust PR #138961](https://github.com/rust-lang/rust/pull/138961).
432+
405433
r[type.closure.capture.precision.slice-patterns.arrays]
406434
As the length of an array is fixed by its type, matching an array against a slice pattern does not by itself capture the place.
407435

0 commit comments

Comments
 (0)