Skip to content

Commit 73f5eb7

Browse files
committed
---
yaml --- r: 228995 b: refs/heads/try c: 987a868 h: refs/heads/master i: 228993: 058602b 228991: 8ca3f99 v: v3
1 parent a30bf14 commit 73f5eb7

File tree

4 files changed

+80
-25
lines changed

4 files changed

+80
-25
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
refs/heads/master: aca2057ed5fb7af3f8905b2bc01f72fa001c35c8
33
refs/heads/snap-stage3: 1af31d4974e33027a68126fa5a5a3c2c6491824f
4-
refs/heads/try: 35b8001f684399992978c60fcb3d51232b3ca85d
4+
refs/heads/try: 987a8687db1a2a5a9388265a6bb5a1590a05dd69
55
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
66
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596
77
refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503

branches/try/SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
* [Transmutes](transmutes.md)
2424
* [Uninitialized Memory](uninitialized.md)
2525
* [Checked](checked-uninit.md)
26+
* [Drop Flags](drop-flags.md)
2627
* [Unchecked](unchecked-uninit.md)
2728
* [Ownership-Oriented Resource Management](raii.md)
2829
* [Constructors](constructors.md)

branches/try/checked-uninit.md

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -83,27 +83,3 @@ fn main() {
8383
However reassigning `y` in this example *would* require `y` to be marked as
8484
mutable, as a Safe Rust program could observe that the value of `y` changed.
8585
Otherwise the variable is exactly like new.
86-
87-
This raises an interesting question with respect to `Drop`: where does Rust try
88-
to call the destructor of a variable that is conditionally initialized? It turns
89-
out that Rust actually tracks whether a type should be dropped or not *at
90-
runtime*. As a variable becomes initialized and uninitialized, a *drop flag* for
91-
that variable is set and unset. When a variable goes out of scope or is assigned
92-
a value, it evaluates whether the current value of the variable should be dropped.
93-
Of course, static analysis can remove these checks. If the compiler can prove that
94-
a value is guaranteed to be either initialized or not, then it can theoretically
95-
generate more efficient code! As such it may be desirable to structure code to
96-
have *static drop semantics* when possible.
97-
98-
As of Rust 1.0, the drop flags are actually not-so-secretly stashed in a hidden
99-
field of any type that implements Drop. The language sets the drop flag by
100-
overwriting the entire struct with a particular value. This is pretty obviously
101-
Not The Fastest and causes a bunch of trouble with optimizing code. As such work
102-
is currently under way to move the flags out onto the stack frame where they
103-
more reasonably belong. Unfortunately this work will take some time as it
104-
requires fairly substantial changes to the compiler.
105-
106-
So in general, Rust programs don't need to worry about uninitialized values on
107-
the stack for correctness. Although they might care for performance. Thankfully,
108-
Rust makes it easy to take control here! Uninitialized values are there, and
109-
Safe Rust lets you work with them, but you're never in danger.

branches/try/drop-flags.md

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
% Drop Flags
2+
3+
The examples in the previous section introduce an interesting problem for Rust.
4+
We have seen that's possible to conditionally initialize, deinitialize, and
5+
*reinitialize* locations of memory totally safely. For Copy types, this isn't
6+
particularly notable since they're just a random pile of bits. However types with
7+
destructors are a different story: Rust needs to know whether to call a destructor
8+
whenever a variable is assigned to, or a variable goes out of scope. How can it
9+
do this with conditional initialization?
10+
11+
It turns out that Rust actually tracks whether a type should be dropped or not *at
12+
runtime*. As a variable becomes initialized and uninitialized, a *drop flag* for
13+
that variable is toggled. When a variable *might* need to be dropped, this flag
14+
is evaluated to determine if it *should* be dropped.
15+
16+
Of course, it is *often* the case that a value's initialization state can be
17+
*statically* known at every point in the program. If this is the case, then the
18+
compiler can theoretically generate more effecient code! For instance,
19+
straight-line code has such *static drop semantics*:
20+
21+
```rust
22+
let mut x = Box::new(0); // x was uninit
23+
let mut y = x; // y was uninit
24+
x = Box::new(0); // x was uninit
25+
y = x; // y was init; Drop y!
26+
// y was init; Drop y!
27+
// x was uninit
28+
```
29+
30+
And even branched code where all branches have the same behaviour with respect
31+
to initialization:
32+
33+
```rust
34+
let mut x = Box::new(0); // x was uninit
35+
if condition {
36+
drop(x) // x gets moved out
37+
} else {
38+
println!("{}", x);
39+
drop(x) // x gets moved out
40+
}
41+
x = Box::new(0); // x was uninit
42+
// x was init; Drop x!
43+
```
44+
45+
However code like this *requires* runtime information to correctly Drop:
46+
47+
```rust
48+
let x;
49+
if condition {
50+
x = Box::new(0); // x was uninit
51+
println!("{}", x);
52+
}
53+
// x might be uninit; check the flag!
54+
```
55+
56+
Of course, in this case it's trivial to retrieve static drop semantics:
57+
58+
```rust
59+
if condition {
60+
let x = Box::new(0);
61+
println!("{}", x);
62+
}
63+
```
64+
65+
As of Rust 1.0, the drop flags are actually not-so-secretly stashed in a hidden
66+
field of any type that implements Drop. Rust sets the drop flag by
67+
overwriting the *entire* value with a particular byte. This is pretty obviously
68+
Not The Fastest and causes a bunch of trouble with optimizing code. It's legacy
69+
from a time when you could do much more complex conditional initialization.
70+
71+
As such work is currently under way to move the flags out onto the stack frame
72+
where they more reasonably belong. Unfortunately, this work will take some time
73+
as it requires fairly substantial changes to the compiler.
74+
75+
Regardless, Rust programs don't need to worry about uninitialized values on
76+
the stack for correctness. Although they might care for performance. Thankfully,
77+
Rust makes it easy to take control here! Uninitialized values are there, and
78+
you can work with them in Safe Rust, but you're *never* in danger.

0 commit comments

Comments
 (0)