Skip to content

Commit b07b925

Browse files
authored
Merge pull request #2073 from dianne/deref-desugar-scoping-difference
Note scoping differences between `*x` and `*x.deref()` , and `a[b]` and `*a.index(b)`
2 parents 7446bf9 + 8e4d81a commit b07b925

2 files changed

Lines changed: 34 additions & 2 deletions

File tree

src/expressions/array-expr.md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,22 @@ r[expr.array.index.array]
8484
[Array] and [slice]-typed values can be indexed by writing a square-bracket-enclosed expression of type `usize` (the index) after them. When the array is mutable, the resulting [memory location] can be assigned to.
8585

8686
r[expr.array.index.trait]
87-
For other types an index expression `a[b]` is equivalent to `*std::ops::Index::index(&a, b)`, or `*std::ops::IndexMut::index_mut(&mut a, b)` in a mutable place expression context. Just as with methods, Rust will also insert dereference operations on `a` repeatedly to find an implementation.
87+
For other types an index expression `a[b]` is equivalent to `*std::ops::Index::index(&a, b)`, or `*std::ops::IndexMut::index_mut(&mut a, b)` in a mutable place expression context, except that when the index expression undergoes [temporary lifetime extension], the indexed expression `a` also has its [temporary scope] extended. Just as with methods, Rust will also insert dereference operations on `a` repeatedly to find an implementation.
88+
89+
```rust
90+
// The temporary holding the result of `vec![()]` is extended to
91+
// live to the end of the block, so `x` may be used in subsequent
92+
// statements.
93+
let x = &vec![()][0];
94+
# x;
95+
```
96+
97+
```rust,compile_fail,E0716
98+
// The temporary holding the result of `vec![()]` is dropped at the
99+
// end of the statement, so it's an error to use `y` after.
100+
let y = &*std::ops::Index::index(&vec![()], 0); // ERROR
101+
# y;
102+
```
88103

89104
r[expr.array.index.zero-index]
90105
Indices are zero-based for arrays and slices.
@@ -127,3 +142,5 @@ The array index expression can be implemented for types other than arrays and sl
127142
[panic]: ../panic.md
128143
[path]: path-expr.md
129144
[slice]: ../types/slice.md
145+
[temporary lifetime extension]: destructors.scope.lifetime-extension
146+
[temporary scope]: destructors.scope.temporary

src/expressions/operator-expr.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ r[expr.deref.safety]
176176
Dereferencing a raw pointer requires `unsafe`.
177177

178178
r[expr.deref.traits]
179-
On non-pointer types `*x` is equivalent to `*std::ops::Deref::deref(&x)` in an [immutable place expression context](../expressions.md#mutability) and `*std::ops::DerefMut::deref_mut(&mut x)` in a mutable place expression context.
179+
On non-pointer types `*x` is equivalent to `*std::ops::Deref::deref(&x)` in an [immutable place expression context](../expressions.md#mutability) and `*std::ops::DerefMut::deref_mut(&mut x)` in a mutable place expression context, except that when `*x` undergoes [temporary lifetime extension], the dereferenced expression `x` also has its [temporary scope] extended.
180180

181181
```rust
182182
# struct NoCopy;
@@ -189,6 +189,21 @@ let c = Box::new(NoCopy);
189189
let d: NoCopy = *c;
190190
```
191191

192+
```rust
193+
// The temporary holding the result of `String::new()` is extended
194+
// to live to the end of the block, so `x` may be used in subsequent
195+
// statements.
196+
let x = &*String::new();
197+
# x;
198+
```
199+
200+
```rust,compile_fail,E0716
201+
// The temporary holding the result of `String::new()` is dropped at
202+
// the end of the statement, so it's an error to use `y` after.
203+
let y = &*std::ops::Deref::deref(&String::new()); // ERROR
204+
# y;
205+
```
206+
192207
r[expr.try]
193208
## The try propagation expression
194209

0 commit comments

Comments
 (0)