about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlexis Beingessner <a.beingessner@gmail.com>2015-07-27 14:40:54 -0700
committerAlexis Beingessner <a.beingessner@gmail.com>2015-07-27 14:42:04 -0700
commitb53406f8241edb45eb962795da99cb2cf73d8c1a (patch)
treef2d470b38a85d0139d3ab9eafb55fd13498b7f53
parent8c7111da07f20422a6bd5243b56d302f0f02c3a5 (diff)
downloadrust-b53406f8241edb45eb962795da99cb2cf73d8c1a.tar.gz
rust-b53406f8241edb45eb962795da99cb2cf73d8c1a.zip
fixups for aturon
-rw-r--r--src/doc/tarpl/lifetimes.md4
-rw-r--r--src/doc/tarpl/references.md62
-rw-r--r--src/doc/tarpl/subtyping.md2
3 files changed, 43 insertions, 25 deletions
diff --git a/src/doc/tarpl/lifetimes.md b/src/doc/tarpl/lifetimes.md
index 350a4ead130..f4475b73850 100644
--- a/src/doc/tarpl/lifetimes.md
+++ b/src/doc/tarpl/lifetimes.md
@@ -19,7 +19,7 @@ our toes with lifetimes, we're going to pretend that we're actually allowed
 to label scopes with lifetimes, and desugar the examples from the start of
 this chapter.
 
-Our examples made use of *aggressive* sugar -- high fructose corn syrup even --
+Originally, our examples made use of *aggressive* sugar -- high fructose corn syrup even --
 around scopes and lifetimes, because writing everything out explicitly is
 *extremely noisy*. All Rust code relies on aggressive inference and elision of
 "obvious" things.
@@ -166,7 +166,7 @@ our implementation *just a bit*.)
 
 
 
-# Example 2: aliasing a mutable reference
+# Example: aliasing a mutable reference
 
 How about the other example:
 
diff --git a/src/doc/tarpl/references.md b/src/doc/tarpl/references.md
index a109bf5d012..da70dd52907 100644
--- a/src/doc/tarpl/references.md
+++ b/src/doc/tarpl/references.md
@@ -1,5 +1,12 @@
 % References
 
+This section gives a high-level view of the memory model that *all* Rust
+programs must satisfy to be correct. Safe code is statically verified
+to obey this model by the borrow checker. Unsafe code may go above
+and beyond the borrow checker while still satisfying this model. The borrow
+checker may also be extended to allow more programs to compile, as long as
+this more fundamental model is satisfied.
+
 There are two kinds of reference:
 
 * Shared reference: `&`
@@ -7,53 +14,63 @@ There are two kinds of reference:
 
 Which obey the following rules:
 
-* A reference cannot outlive its referent A mutable reference cannot be aliased
+* A reference cannot outlive its referent
+* A mutable reference cannot be aliased
 
-To define aliasing, we must define the notion of *paths* and *liveness*.
+That's it. That's the whole model. Of course, we should probably define
+what *aliased* means. To define aliasing, we must define the notion of
+*paths* and *liveness*.
 
 
 
 
 # Paths
 
-If all Rust had were values, then every value would be uniquely owned by a
-variable or composite structure. From this we naturally derive a *tree* of
-ownership. The stack itself is the root of the tree, with every variable as its
-direct children. Each variable's direct children would be their fields (if any),
-and so on.
+If all Rust had were values (no pointers), then every value would be uniquely
+owned by a variable or composite structure. From this we naturally derive a
+*tree* of ownership. The stack itself is the root of the tree, with every
+variable as its direct children. Each variable's direct children would be their
+fields (if any), and so on.
 
 From this view, every value in Rust has a unique *path* in the tree of
-ownership. References to a value can subsequently be interpreted as a path in
-this tree. Of particular interest are *ancestors* and *descendants*: if `x` owns
-`y`, then `x` is an *ancestor* of `y`, and `y` is a *descendant* of `x`. Note
+ownership. Of particular interest are *ancestors* and *descendants*: if `x` owns
+`y`, then `x` is an ancestor of `y`, and `y` is a descendant of `x`. Note
 that this is an inclusive relationship: `x` is a descendant and ancestor of
 itself.
 
+We can then define references as simply *names* for paths. When you create a
+reference, you're declaring that an ownership path exists to this address
+of memory.
+
 Tragically, plenty of data doesn't reside on the stack, and we must also
 accommodate this. Globals and thread-locals are simple enough to model as
 residing at the bottom of the stack (though we must be careful with mutable
 globals). Data on the heap poses a different problem.
 
 If all Rust had on the heap was data uniquely owned by a pointer on the stack,
-then we can just treat that pointer as a struct that owns the value on the heap.
-Box, Vec, String, and HashMap, are examples of types which uniquely own data on
-the heap.
+then we could just treat such a pointer as a struct that owns the value on the
+heap. Box, Vec, String, and HashMap, are examples of types which uniquely
+own data on the heap.
 
 Unfortunately, data on the heap is not *always* uniquely owned. Rc for instance
-introduces a notion of *shared* ownership. Shared ownership means there is no
-unique path. A value with no unique path limits what we can do with it. In
-general, only shared references can be created to these values. However
+introduces a notion of *shared* ownership. Shared ownership of a value means
+there is no unique path to it. A value with no unique path limits what we can do
+with it.
+
+In general, only shared references can be created to non-unique paths. However
 mechanisms which ensure mutual exclusion may establish One True Owner
-temporarily, establishing a unique path to that value (and therefore all its
-children).
+temporarily, establishing a unique path to that value (and therefore all
+its children). If this is done, the value may be mutated. In particular, a
+mutable reference can be taken.
 
 The most common way to establish such a path is through *interior mutability*,
 in contrast to the *inherited mutability* that everything in Rust normally uses.
 Cell, RefCell, Mutex, and RWLock are all examples of interior mutability types.
-These types provide exclusive access through runtime restrictions. However it is
-also possible to establish unique ownership without interior mutability. For
-instance, if an Rc has refcount 1, then it is safe to mutate or move its
-internals.
+These types provide exclusive access through runtime restrictions.
+
+An interesting case of this effect is Rc itself: if an Rc has refcount 1,
+then it is safe to mutate or even move its internals. Note however that the
+refcount itself uses interior mutability.
 
 In order to correctly communicate to the type system that a variable or field of
 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.
 
 
 
+
 # Liveness
 
 Note: Liveness is not the same thing as a *lifetime*, which will be explained
diff --git a/src/doc/tarpl/subtyping.md b/src/doc/tarpl/subtyping.md
index 1b33c9abaa1..8c5ac9cca6b 100644
--- a/src/doc/tarpl/subtyping.md
+++ b/src/doc/tarpl/subtyping.md
@@ -100,7 +100,7 @@ subsequently be dropped, and `forever_str` would point to freed memory when we
 print it! Therefore `&mut` should be invariant.
 
 This is the general theme of variance vs invariance: if variance would allow you
-to *store* a short-lived value over a longer-lived slot, then you must be
+to store a short-lived value into a longer-lived slot, then you must be
 invariant.
 
 However it *is* sound for `&'a mut T` to be variant over `'a`. The key difference