Skip to content

Commit b53406f

Browse files
committed
fixups for aturon
1 parent 8c7111d commit b53406f

File tree

3 files changed

+43
-25
lines changed

3 files changed

+43
-25
lines changed

src/doc/tarpl/lifetimes.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ our toes with lifetimes, we're going to pretend that we're actually allowed
1919
to label scopes with lifetimes, and desugar the examples from the start of
2020
this chapter.
2121

22-
Our examples made use of *aggressive* sugar -- high fructose corn syrup even --
22+
Originally, our examples made use of *aggressive* sugar -- high fructose corn syrup even --
2323
around scopes and lifetimes, because writing everything out explicitly is
2424
*extremely noisy*. All Rust code relies on aggressive inference and elision of
2525
"obvious" things.
@@ -166,7 +166,7 @@ our implementation *just a bit*.)
166166

167167

168168

169-
# Example 2: aliasing a mutable reference
169+
# Example: aliasing a mutable reference
170170

171171
How about the other example:
172172

src/doc/tarpl/references.md

Lines changed: 40 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,76 @@
11
% References
22

3+
This section gives a high-level view of the memory model that *all* Rust
4+
programs must satisfy to be correct. Safe code is statically verified
5+
to obey this model by the borrow checker. Unsafe code may go above
6+
and beyond the borrow checker while still satisfying this model. The borrow
7+
checker may also be extended to allow more programs to compile, as long as
8+
this more fundamental model is satisfied.
9+
310
There are two kinds of reference:
411

512
* Shared reference: `&`
613
* Mutable reference: `&mut`
714

815
Which obey the following rules:
916

10-
* A reference cannot outlive its referent A mutable reference cannot be aliased
17+
* A reference cannot outlive its referent
18+
* A mutable reference cannot be aliased
1119

12-
To define aliasing, we must define the notion of *paths* and *liveness*.
20+
That's it. That's the whole model. Of course, we should probably define
21+
what *aliased* means. To define aliasing, we must define the notion of
22+
*paths* and *liveness*.
1323

1424

1525

1626

1727
# Paths
1828

19-
If all Rust had were values, then every value would be uniquely owned by a
20-
variable or composite structure. From this we naturally derive a *tree* of
21-
ownership. The stack itself is the root of the tree, with every variable as its
22-
direct children. Each variable's direct children would be their fields (if any),
23-
and so on.
29+
If all Rust had were values (no pointers), then every value would be uniquely
30+
owned by a variable or composite structure. From this we naturally derive a
31+
*tree* of ownership. The stack itself is the root of the tree, with every
32+
variable as its direct children. Each variable's direct children would be their
33+
fields (if any), and so on.
2434

2535
From this view, every value in Rust has a unique *path* in the tree of
26-
ownership. References to a value can subsequently be interpreted as a path in
27-
this tree. Of particular interest are *ancestors* and *descendants*: if `x` owns
28-
`y`, then `x` is an *ancestor* of `y`, and `y` is a *descendant* of `x`. Note
36+
ownership. Of particular interest are *ancestors* and *descendants*: if `x` owns
37+
`y`, then `x` is an ancestor of `y`, and `y` is a descendant of `x`. Note
2938
that this is an inclusive relationship: `x` is a descendant and ancestor of
3039
itself.
3140

41+
We can then define references as simply *names* for paths. When you create a
42+
reference, you're declaring that an ownership path exists to this address
43+
of memory.
44+
3245
Tragically, plenty of data doesn't reside on the stack, and we must also
3346
accommodate this. Globals and thread-locals are simple enough to model as
3447
residing at the bottom of the stack (though we must be careful with mutable
3548
globals). Data on the heap poses a different problem.
3649

3750
If all Rust had on the heap was data uniquely owned by a pointer on the stack,
38-
then we can just treat that pointer as a struct that owns the value on the heap.
39-
Box, Vec, String, and HashMap, are examples of types which uniquely own data on
40-
the heap.
51+
then we could just treat such a pointer as a struct that owns the value on the
52+
heap. Box, Vec, String, and HashMap, are examples of types which uniquely
53+
own data on the heap.
4154

4255
Unfortunately, data on the heap is not *always* uniquely owned. Rc for instance
43-
introduces a notion of *shared* ownership. Shared ownership means there is no
44-
unique path. A value with no unique path limits what we can do with it. In
45-
general, only shared references can be created to these values. However
56+
introduces a notion of *shared* ownership. Shared ownership of a value means
57+
there is no unique path to it. A value with no unique path limits what we can do
58+
with it.
59+
60+
In general, only shared references can be created to non-unique paths. However
4661
mechanisms which ensure mutual exclusion may establish One True Owner
47-
temporarily, establishing a unique path to that value (and therefore all its
48-
children).
62+
temporarily, establishing a unique path to that value (and therefore all
63+
its children). If this is done, the value may be mutated. In particular, a
64+
mutable reference can be taken.
4965

5066
The most common way to establish such a path is through *interior mutability*,
5167
in contrast to the *inherited mutability* that everything in Rust normally uses.
5268
Cell, RefCell, Mutex, and RWLock are all examples of interior mutability types.
53-
These types provide exclusive access through runtime restrictions. However it is
54-
also possible to establish unique ownership without interior mutability. For
55-
instance, if an Rc has refcount 1, then it is safe to mutate or move its
56-
internals.
69+
These types provide exclusive access through runtime restrictions.
70+
71+
An interesting case of this effect is Rc itself: if an Rc has refcount 1,
72+
then it is safe to mutate or even move its internals. Note however that the
73+
refcount itself uses interior mutability.
5774

5875
In order to correctly communicate to the type system that a variable or field of
5976
a struct can have interior mutability, it must be wrapped in an UnsafeCell. This
@@ -62,6 +79,7 @@ that value. You still must yourself ensure that mutual exclusion is upheld.
6279

6380

6481

82+
6583
# Liveness
6684

6785
Note: Liveness is not the same thing as a *lifetime*, which will be explained

src/doc/tarpl/subtyping.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ subsequently be dropped, and `forever_str` would point to freed memory when we
100100
print it! Therefore `&mut` should be invariant.
101101

102102
This is the general theme of variance vs invariance: if variance would allow you
103-
to *store* a short-lived value over a longer-lived slot, then you must be
103+
to store a short-lived value into a longer-lived slot, then you must be
104104
invariant.
105105

106106
However it *is* sound for `&'a mut T` to be variant over `'a`. The key difference

0 commit comments

Comments
 (0)