about summary refs log tree commit diff
path: root/doc/tutorial-borrowed-ptr.md
diff options
context:
space:
mode:
Diffstat (limited to 'doc/tutorial-borrowed-ptr.md')
-rw-r--r--doc/tutorial-borrowed-ptr.md161
1 files changed, 4 insertions, 157 deletions
diff --git a/doc/tutorial-borrowed-ptr.md b/doc/tutorial-borrowed-ptr.md
index c13b2528598..0c1624706bf 100644
--- a/doc/tutorial-borrowed-ptr.md
+++ b/doc/tutorial-borrowed-ptr.md
@@ -348,12 +348,12 @@ mutations:
 ~~~ {.xfail-test}
 fn example3() -> int {
     struct R { g: int }
-    struct S { mut f: ~R }
+    struct S { f: ~R }
 
-    let mut x = ~S {mut f: ~R {g: 3}};
+    let mut x = ~S {f: ~R {g: 3}};
     let y = &x.f.g;
-    x = ~S {mut f: ~R {g: 4}}; // Error reported here.
-    x.f = ~R {g: 5};           // Error reported here.
+    x = ~S {f: ~R {g: 4}};  // Error reported here.
+    x.f = ~R {g: 5};        // Error reported here.
     *y
 }
 ~~~
@@ -362,91 +362,6 @@ In this case, two errors are reported, one when the variable `x` is
 modified and another when `x.f` is modified. Either modification would
 invalidate the pointer `y`.
 
-Things get trickier when the unique box is not uniquely owned by the
-stack frame, or when there is no way for the compiler to determine the
-box's owner. Consider a program like this:
-
-~~~ {.xfail-test}
-struct R { g: int }
-struct S { mut f: ~R }
-fn example5a(x: @S, callback: @fn()) -> int {
-    let y = &x.f.g;   // Error reported here.
-    ...
-    callback();
-    ...
-#   return 0;
-}
-~~~
-
-Here the heap looks something like:
-
-~~~ {.notrust}
-     Stack            Managed Heap       Exchange Heap
-
-  x +------+        +-------------+       +------+
-    | @... | ---->  | mut f: ~... | --+-> | g: 3 |
-  y +------+        +-------------+   |   +------+
-    | &int | -------------------------+
-    +------+
-~~~
-
-In this case, the owning reference to the value being borrowed is
-`x.f`. Moreover, `x.f` is both mutable and *aliasable*. Aliasable
-means that there may be other pointers to that same managed box, so
-even if the compiler were to prove an absence of mutations to `x.f`,
-code could mutate `x.f` indirectly by changing an alias of
-`x`. Therefore, to be safe, the compiler only accepts *pure* actions
-during the lifetime of `y`. We define what "pure" means in the section
-on [purity](#purity).
-
-Besides ensuring purity, the only way to borrow the interior of a
-unique found in aliasable memory is to ensure that the borrowed field
-itself is also unique, as in the following example:
-
-~~~
-struct R { g: int }
-struct S { f: ~R }
-fn example5b(x: @S) -> int {
-    let y = &x.f.g;
-    ...
-# return 0;
-}
-~~~
-
-Here, the field `f` is not declared as mutable. But that is enough for
-the compiler to know that, even if aliases to `x` exist, the field `f`
-cannot be changed and hence the unique box `g` will remain valid.
-
-If you do have a unique box in a mutable field, and you wish to borrow
-it, one option is to use the swap operator to move that unique box
-onto your stack:
-
-~~~
-struct R { g: int }
-struct S { mut f: ~R }
-fn example5c(x: @S) -> int {
-    let mut v = ~R {g: 0};
-    v <-> x.f;         // Swap v and x.f
-    { // Block constrains the scope of `y`:
-        let y = &v.g;
-        ...
-    }
-    x.f = v;          // Replace x.f
-    ...
-# return 0;
-}
-~~~
-
-Of course, this has the side effect of modifying your managed box for
-the duration of the borrow, so it only works when you know that you
-won't be accessing that same box for the duration of the loan. Also,
-it is sometimes necessary to introduce additional blocks to constrain
-the scope of the loan.  In this example, the borrowed pointer `y`
-would still be in scope when you moved the value `v` back into `x.f`,
-and hence moving `v` would be considered illegal.  You cannot move
-values if they are the targets of valid outstanding loans. Introducing
-the block restricts the scope of `y`, making the move legal.
-
 # Borrowing and enums
 
 The previous example showed that the type system forbids any borrowing
@@ -558,11 +473,6 @@ permit `ref` bindings into data owned by the stack frame even if the
 data are mutable, but otherwise it requires that the data reside in
 immutable memory.
 
-> ***Note:*** Right now, pattern bindings not explicitly annotated
-> with `ref` or `copy` use a special mode of "implicit by reference".
-> This is changing as soon as we finish updating all the existing code
-> in the compiler that relies on the current settings.
-
 # Returning borrowed pointers
 
 So far, all of the examples we've looked at use borrowed pointers in a
@@ -745,69 +655,6 @@ fn select<T>(shape: &Shape, threshold: float,
 
 This is equivalent to the previous definition.
 
-# Purity
-
-As mentioned before, the Rust compiler offers a kind of escape hatch
-that permits borrowing of any data, as long as the actions that occur
-during the lifetime of the borrow are pure. Pure actions are those
-that only modify data owned by the current stack frame. The compiler
-can therefore permit arbitrary pointers into the heap, secure in the
-knowledge that no pure action will ever cause them to become
-invalidated (the compiler must still track data on the stack which is
-borrowed and enforce those rules normally, of course). A pure function
-in Rust is referentially transparent: it returns the same results
-given the same (observably equivalent) inputs. That is because while
-pure functions are allowed to modify data, they may only modify
-*stack-local* data, which cannot be observed outside the scope of the
-function itself. (Using an `unsafe` block invalidates this guarantee.)
-
-Let’s revisit a previous example and show how purity can affect
-typechecking. Here is `example5a()`, which borrows the interior of a
-unique box found in an aliasable, mutable location, only now we’ve
-replaced the `...` with some specific code:
-
-~~~
-struct R { g: int }
-struct S { mut f: ~R }
-fn example5a(x: @S ...) -> int {
-    let y = &x.f.g;   // Unsafe
-    *y + 1        
-}
-~~~
-
-The new code simply returns an incremented version of `y`. This code
-clearly doesn't mutate the heap, so the compiler is satisfied.
-
-But suppose we wanted to pull the increment code into a helper, like
-this:
-
-~~~
-fn add_one(x: &int) -> int { *x + 1 }
-~~~
-
-We can now update `example5a()` to use `add_one()`:
-
-~~~
-# struct R { g: int }
-# struct S { mut f: ~R }
-# pure fn add_one(x: &int) -> int { *x + 1 }
-fn example5a(x: @S ...) -> int {
-    let y = &x.f.g;
-    add_one(y)        // Error reported here
-}
-~~~
-
-But now the compiler will report an error again. The reason is that it
-only considers one function at a time (like most typecheckers), and
-so it does not know that `add_one()` consists of pure code. We can
-help the compiler by labeling `add_one()` as pure:
-
-~~~
-pure fn add_one(x: &int) -> int { *x + 1 }
-~~~
-
-With this change, the modified version of `example5a()` will again compile.
-
 # Conclusion
 
 So there you have it: a (relatively) brief tour of the borrowed pointer