Skip to content

Commit d8c164b

Browse files
committed
Add a note about scoping differences between *x and *x.deref()
1 parent e122eef commit d8c164b

File tree

1 file changed

+28
-0
lines changed

1 file changed

+28
-0
lines changed

src/expressions/operator-expr.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,34 @@ let y = &mut 9;
189189
assert_eq!(*y, 11);
190190
```
191191

192+
> [!NOTE]
193+
> The [temporary scopes][temporary scope] of `x` in `*x` and `*std::ops::Deref::deref(&x)` are not always the same in all immutable place expression contexts.
194+
> Likewise, the temporary scopes of `x` in `*x` and `*std::ops::DerefMut::deref_mut(&mut x)` are not always the same in all mutable place expression contexts.
195+
>
196+
> If `*x` has an [extended][temporary lifetime extension] temporary scope, then `x` does as well ([destructors.scope.lifetime-extension.sub-expressions]).
197+
> However, the same does not apply to `*std::ops::Deref::deref(&x)` or `*std::ops::DerefMut::deref_mut(&mut x)`.
198+
>
199+
> For example, this affects automatically reference-counted pointers:
200+
>
201+
> ```rust
202+
> use std::rc::Rc;
203+
>
204+
> let rc = Rc::new(());
205+
> // The reference count starts at 1.
206+
> assert_eq!(Rc::strong_count(&rc), 1);
207+
>
208+
> let ref x = *std::ops::Deref::deref(&rc.clone());
209+
> // `rc.clone()` increments the reference count, but its result is
210+
> // dropped at the end of the statement, so the reference count goes
211+
> // back to 1.
212+
> assert_eq!(Rc::strong_count(&rc), 1);
213+
>
214+
> let ref y = *rc.clone();
215+
> // In this case, the lifetime of `rc.clone()` is extended to the end
216+
> // of the block, so the reference count stays at 2.
217+
> assert_eq!(Rc::strong_count(&rc), 2);
218+
> ```
219+
192220
r[expr.try]
193221
## The try propagation expression
194222

0 commit comments

Comments
 (0)