Skip to content

Commit 898e478

Browse files
committed
can't forget non-lexical lifetimes!
1 parent 9af1cbe commit 898e478

File tree

2 files changed

+84
-0
lines changed

2 files changed

+84
-0
lines changed

src/SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
- [No more anonymous parameters](rust-2018/trait-system/no-anon-params.md)
3737
- [Slice patterns](rust-2018/slice-patterns.md)
3838
- [Ownership and lifetimes](rust-2018/ownership-and-lifetimes/index.md)
39+
- [Non-lexical lifetimes](rust-2018/ownership-and-lifetimes/non-lexical-lifetimes.md)
3940
- [Default `match` bindings](rust-2018/ownership-and-lifetimes/default-match-bindings.md)
4041
- [`'_`, the anonymous lifetime](rust-2018/ownership-and-lifetimes/the-anonymous-lifetime.md)
4142
- [Lifetime elision in `impl`](rust-2018/ownership-and-lifetimes/lifetime-elision-in-impl.md)
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# Non-lexical lifetimes
2+
3+
![Minimum Rust version: beta](https://img.shields.io/badge/Minimum%20Rust%20Version-beta-orange.svg)
4+
5+
The borrow checker has been enhanced to accept more code, via a mechanism
6+
called "non-lexial lifetimes." Consider this example:
7+
8+
```rust,ignore
9+
fn main() {
10+
let mut x = 5;
11+
12+
let y = &x;
13+
14+
let z = &mut x;
15+
}
16+
```
17+
18+
In older Rust, this is a compile-time error:
19+
20+
```text
21+
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
22+
--> src/main.rs:5:18
23+
|
24+
4 | let y = &x;
25+
| - immutable borrow occurs here
26+
5 | let z = &mut x;
27+
| ^ mutable borrow occurs here
28+
6 | }
29+
| - immutable borrow ends here
30+
```
31+
32+
This is because lifetimes follow "lexical scope"; that is, the borrow from `y` is
33+
considered to be held until `y` goes out of scope at the end of `main`, even though
34+
we never use `y` again. This code is fine, but the borrow checker could not handle it.
35+
36+
Today, this code will compile just fine.
37+
38+
## Better errors
39+
40+
What if we did use `y`, like this?
41+
42+
```rust,ignore
43+
fn main() {
44+
let mut x = 5;
45+
let y = &x;
46+
let z = &mut x;
47+
48+
println!("y: {}", y);
49+
}
50+
```
51+
52+
Here's the error:
53+
54+
```text
55+
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
56+
--> src/main.rs:5:18
57+
|
58+
4 | let y = &x;
59+
| - immutable borrow occurs here
60+
5 | let z = &mut x;
61+
| ^ mutable borrow occurs here
62+
...
63+
8 | }
64+
| - immutable borrow ends here
65+
```
66+
67+
With non-lexial lifetime, the error changes slightly:
68+
69+
```text
70+
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
71+
--> src/main.rs:5:13
72+
|
73+
4 | let y = &x;
74+
| -- immutable borrow occurs here
75+
5 | let z = &mut x;
76+
| ^^^^^^ mutable borrow occurs here
77+
6 |
78+
7 | println!("y: {}", y);
79+
| - borrow later used here
80+
```
81+
82+
instead of pointing to where `y` goes out of scope, it insteads shows you where
83+
the conflicting borrow occurs. This makes these sorts of errors *far* easier to debug.

0 commit comments

Comments
 (0)