]> git.lizzy.rs Git - rust.git/commitdiff
Convert sub tutorials into Guides #10838
authorAlan Andrade <alan.andradec@gmail.com>
Sat, 21 Dec 2013 23:29:48 +0000 (17:29 -0600)
committerAlan Andrade <alan.andradec@gmail.com>
Mon, 6 Jan 2014 04:48:19 +0000 (22:48 -0600)
Ensure configure creates doc/guides directory

Fix configure makefile and tests

Remove old guides dir and configure option, convert testing to guide

Remove ignored files

Fix submodule issue

prepend dir in makefile so that bor knows how to build the docs

S to uppercase

20 files changed:
configure
doc/guide-borrowed-ptr.md [new file with mode: 0644]
doc/guide-conditions.md [new file with mode: 0644]
doc/guide-container.md [new file with mode: 0644]
doc/guide-ffi.md [new file with mode: 0644]
doc/guide-macros.md [new file with mode: 0644]
doc/guide-rustpkg.md [new file with mode: 0644]
doc/guide-tasks.md [new file with mode: 0644]
doc/guide-testing.md [new file with mode: 0644]
doc/tutorial-borrowed-ptr.md [deleted file]
doc/tutorial-conditions.md [deleted file]
doc/tutorial-container.md [deleted file]
doc/tutorial-ffi.md [deleted file]
doc/tutorial-macros.md [deleted file]
doc/tutorial-rustpkg.md [deleted file]
doc/tutorial-tasks.md [deleted file]
doc/tutorial-testing.md [deleted file]
doc/tutorial.md
mk/docs.mk
mk/tests.mk

index 1e3d8b30e115c2c1f4240e33b964be72a7717e2b..89edb69f8665d1bb4c14ddd47e9edc8a8097e769 100755 (executable)
--- a/configure
+++ b/configure
@@ -792,12 +792,12 @@ do
     make_dir $h/test/debug-info
     make_dir $h/test/codegen
     make_dir $h/test/doc-tutorial
-    make_dir $h/test/doc-tutorial-ffi
-    make_dir $h/test/doc-tutorial-macros
-    make_dir $h/test/doc-tutorial-borrowed-ptr
-    make_dir $h/test/doc-tutorial-container
-    make_dir $h/test/doc-tutorial-tasks
-    make_dir $h/test/doc-tutorial-conditions
+    make_dir $h/test/doc-guide-ffi
+    make_dir $h/test/doc-guide-macros
+    make_dir $h/test/doc-guide-borrowed-ptr
+    make_dir $h/test/doc-guide-container
+    make_dir $h/test/doc-guide-tasks
+    make_dir $h/test/doc-guide-conditions
     make_dir $h/test/doc-rust
 done
 
diff --git a/doc/guide-borrowed-ptr.md b/doc/guide-borrowed-ptr.md
new file mode 100644 (file)
index 0000000..7ad1ee2
--- /dev/null
@@ -0,0 +1,663 @@
+% Rust Borrowed Pointers Guide
+
+# Introduction
+
+Borrowed pointers are one of the more flexible and powerful tools available in
+Rust. A borrowed pointer can point anywhere: into the managed or exchange
+heap, into the stack, and even into the interior of another data structure. A
+borrowed pointer is as flexible as a C pointer or C++ reference. However,
+unlike C and C++ compilers, the Rust compiler includes special static checks
+that ensure that programs use borrowed pointers safely. Another advantage of
+borrowed pointers is that they are invisible to the garbage collector, so
+working with borrowed pointers helps reduce the overhead of automatic memory
+management.
+
+Despite their complete safety, a borrowed pointer's representation at runtime
+is the same as that of an ordinary pointer in a C program. They introduce zero
+overhead. The compiler does all safety checks at compile time.
+
+Although borrowed pointers have rather elaborate theoretical
+underpinnings (region pointers), the core concepts will be familiar to
+anyone who has worked with C or C++. Therefore, the best way to explain
+how they are used—and their limitations—is probably just to work
+through several examples.
+
+# By example
+
+Borrowed pointers are called *borrowed* because they are only valid for
+a limited duration. Borrowed pointers never claim any kind of ownership
+over the data that they point to: instead, they are used for cases
+where you would like to use data for a short time.
+
+As an example, consider a simple struct type `Point`:
+
+~~~
+struct Point {x: f64, y: f64}
+~~~
+
+We can use this simple definition to allocate points in many different ways. For
+example, in this code, each of these three local variables contains a
+point, but allocated in a different place:
+
+~~~
+# struct Point {x: f64, y: f64}
+let on_the_stack :  Point =  Point {x: 3.0, y: 4.0};
+let managed_box  : @Point = @Point {x: 5.0, y: 1.0};
+let owned_box    : ~Point = ~Point {x: 7.0, y: 9.0};
+~~~
+
+Suppose we wanted to write a procedure that computed the distance between any
+two points, no matter where they were stored. For example, we might like to
+compute the distance between `on_the_stack` and `managed_box`, or between
+`managed_box` and `owned_box`. One option is to define a function that takes
+two arguments of type `Point`—that is, it takes the points by value. But if we
+define it this way, calling the function will cause the points to be
+copied. For points, this is probably not so bad, but often copies are
+expensive. Worse, if the data type contains mutable fields, copying can change
+the semantics of your program in unexpected ways. So we'd like to define a
+function that takes the points by pointer. We can use borrowed pointers to do
+this:
+
+~~~
+# struct Point {x: f64, y: f64}
+# fn sqrt(f: f64) -> f64 { 0.0 }
+fn compute_distance(p1: &Point, p2: &Point) -> f64 {
+    let x_d = p1.x - p2.x;
+    let y_d = p1.y - p2.y;
+    sqrt(x_d * x_d + y_d * y_d)
+}
+~~~
+
+Now we can call `compute_distance()` in various ways:
+
+~~~
+# struct Point {x: f64, y: f64}
+# let on_the_stack :  Point =  Point{x: 3.0, y: 4.0};
+# let managed_box  : @Point = @Point{x: 5.0, y: 1.0};
+# let owned_box    : ~Point = ~Point{x: 7.0, y: 9.0};
+# fn compute_distance(p1: &Point, p2: &Point) -> f64 { 0.0 }
+compute_distance(&on_the_stack, managed_box);
+compute_distance(managed_box, owned_box);
+~~~
+
+Here, the `&` operator takes the address of the variable
+`on_the_stack`; this is because `on_the_stack` has the type `Point`
+(that is, a struct value) and we have to take its address to get a
+value. We also call this _borrowing_ the local variable
+`on_the_stack`, because we have created an alias: that is, another
+name for the same data.
+
+In contrast, we can pass the boxes `managed_box` and `owned_box` to
+`compute_distance` directly. The compiler automatically converts a box like
+`@Point` or `~Point` to a borrowed pointer like `&Point`. This is another form
+of borrowing: in this case, the caller lends the contents of the managed or
+owned box to the callee.
+
+Whenever a caller lends data to a callee, there are some limitations on what
+the caller can do with the original. For example, if the contents of a
+variable have been lent out, you cannot send that variable to another task. In
+addition, the compiler will reject any code that might cause the borrowed
+value to be freed or overwrite its component fields with values of different
+types (I'll get into what kinds of actions those are shortly). This rule
+should make intuitive sense: you must wait for a borrower to return the value
+that you lent it (that is, wait for the borrowed pointer to go out of scope)
+before you can make full use of it again.
+
+# Other uses for the & operator
+
+In the previous example, the value `on_the_stack` was defined like so:
+
+~~~
+# struct Point {x: f64, y: f64}
+let on_the_stack: Point = Point {x: 3.0, y: 4.0};
+~~~
+
+This declaration means that code can only pass `Point` by value to other
+functions. As a consequence, we had to explicitly take the address of
+`on_the_stack` to get a borrowed pointer. Sometimes however it is more
+convenient to move the & operator into the definition of `on_the_stack`:
+
+~~~
+# struct Point {x: f64, y: f64}
+let on_the_stack2: &Point = &Point {x: 3.0, y: 4.0};
+~~~
+
+Applying `&` to an rvalue (non-assignable location) is just a convenient
+shorthand for creating a temporary and taking its address. A more verbose
+way to write the same code is:
+
+~~~
+# struct Point {x: f64, y: f64}
+let tmp = Point {x: 3.0, y: 4.0};
+let on_the_stack2 : &Point = &tmp;
+~~~
+
+# Taking the address of fields
+
+As in C, the `&` operator is not limited to taking the address of
+local variables. It can also take the address of fields or
+individual array elements. For example, consider this type definition
+for `rectangle`:
+
+~~~
+struct Point {x: f64, y: f64} // as before
+struct Size {w: f64, h: f64} // as before
+struct Rectangle {origin: Point, size: Size}
+~~~
+
+Now, as before, we can define rectangles in a few different ways:
+
+~~~
+# struct Point {x: f64, y: f64}
+# struct Size {w: f64, h: f64} // as before
+# struct Rectangle {origin: Point, size: Size}
+let rect_stack   = &Rectangle {origin: Point {x: 1.0, y: 2.0},
+                               size: Size {w: 3.0, h: 4.0}};
+let rect_managed = @Rectangle {origin: Point {x: 3.0, y: 4.0},
+                               size: Size {w: 3.0, h: 4.0}};
+let rect_owned   = ~Rectangle {origin: Point {x: 5.0, y: 6.0},
+                               size: Size {w: 3.0, h: 4.0}};
+~~~
+
+In each case, we can extract out individual subcomponents with the `&`
+operator. For example, I could write:
+
+~~~
+# struct Point {x: f64, y: f64} // as before
+# struct Size {w: f64, h: f64} // as before
+# struct Rectangle {origin: Point, size: Size}
+# let rect_stack  = &Rectangle {origin: Point {x: 1.0, y: 2.0}, size: Size {w: 3.0, h: 4.0}};
+# let rect_managed = @Rectangle {origin: Point {x: 3.0, y: 4.0}, size: Size {w: 3.0, h: 4.0}};
+# let rect_owned = ~Rectangle {origin: Point {x: 5.0, y: 6.0}, size: Size {w: 3.0, h: 4.0}};
+# fn compute_distance(p1: &Point, p2: &Point) -> f64 { 0.0 }
+compute_distance(&rect_stack.origin, &rect_managed.origin);
+~~~
+
+which would borrow the field `origin` from the rectangle on the stack
+as well as from the managed box, and then compute the distance between them.
+
+# Borrowing managed boxes and rooting
+
+We’ve seen a few examples so far of borrowing heap boxes, both managed
+and owned. Up till this point, we’ve glossed over issues of
+safety. As stated in the introduction, at runtime a borrowed pointer
+is simply a pointer, nothing more. Therefore, avoiding C's problems
+with dangling pointers requires a compile-time safety check.
+
+The basis for the check is the notion of _lifetimes_. A lifetime is a
+static approximation of the span of execution during which the pointer
+is valid: it always corresponds to some expression or block within the
+program. Code inside that expression can use the pointer without
+restrictions. But if the pointer escapes from that expression (for
+example, if the expression contains an assignment expression that
+assigns the pointer to a mutable field of a data structure with a
+broader scope than the pointer itself), the compiler reports an
+error. We'll be discussing lifetimes more in the examples to come, and
+a more thorough introduction is also available.
+
+When the `&` operator creates a borrowed pointer, the compiler must
+ensure that the pointer remains valid for its entire
+lifetime. Sometimes this is relatively easy, such as when taking the
+address of a local variable or a field that is stored on the stack:
+
+~~~
+struct X { f: int }
+fn example1() {
+    let mut x = X { f: 3 };
+    let y = &mut x.f;  // -+ L
+    ...                //  |
+}                      // -+
+~~~
+
+Here, the lifetime of the borrowed pointer `y` is simply L, the
+remainder of the function body. The compiler need not do any other
+work to prove that code will not free `x.f`. This is true even if the
+code mutates `x`.
+
+The situation gets more complex when borrowing data inside heap boxes:
+
+~~~
+# struct X { f: int }
+fn example2() {
+    let mut x = @X { f: 3 };
+    let y = &x.f;      // -+ L
+    ...                //  |
+}                      // -+
+~~~
+
+In this example, the value `x` is a heap box, and `y` is therefore a
+pointer into that heap box. Again the lifetime of `y` is L, the
+remainder of the function body. But there is a crucial difference:
+suppose `x` were to be reassigned during the lifetime L? If the
+compiler isn't careful, the managed box could become *unrooted*, and
+would therefore be subject to garbage collection. A heap box that is
+unrooted is one such that no pointer values in the heap point to
+it. It would violate memory safety for the box that was originally
+assigned to `x` to be garbage-collected, since a non-heap
+pointer *`y`* still points into it.
+
+> ***Note:*** Our current implementation implements the garbage collector
+> using reference counting and cycle detection.
+
+For this reason, whenever an `&` expression borrows the interior of a
+managed box stored in a mutable location, the compiler inserts a
+temporary that ensures that the managed box remains live for the
+entire lifetime. So, the above example would be compiled as if it were
+written
+
+~~~
+# struct X { f: int }
+fn example2() {
+    let mut x = @X {f: 3};
+    let x1 = x;
+    let y = &x1.f;     // -+ L
+    ...                //  |
+}                      // -+
+~~~
+
+Now if `x` is reassigned, the pointer `y` will still remain valid. This
+process is called *rooting*.
+
+# Borrowing owned boxes
+
+The previous example demonstrated *rooting*, the process by which the
+compiler ensures that managed boxes remain live for the duration of a
+borrow. Unfortunately, rooting does not work for borrows of owned
+boxes, because it is not possible to have two references to a owned
+box.
+
+For owned boxes, therefore, the compiler will only allow a borrow *if
+the compiler can guarantee that the owned box will not be reassigned
+or moved for the lifetime of the pointer*. This does not necessarily
+mean that the owned box is stored in immutable memory. For example,
+the following function is legal:
+
+~~~
+# fn some_condition() -> bool { true }
+# struct Foo { f: int }
+fn example3() -> int {
+    let mut x = ~Foo {f: 3};
+    if some_condition() {
+        let y = &x.f;      // -+ L
+        return *y;         //  |
+    }                      // -+
+    x = ~Foo {f: 4};
+    ...
+# return 0;
+}
+~~~
+
+Here, as before, the interior of the variable `x` is being borrowed
+and `x` is declared as mutable. However, the compiler can prove that
+`x` is not assigned anywhere in the lifetime L of the variable
+`y`. Therefore, it accepts the function, even though `x` is mutable
+and in fact is mutated later in the function.
+
+It may not be clear why we are so concerned about mutating a borrowed
+variable. The reason is that the runtime system frees any owned box
+_as soon as its owning reference changes or goes out of
+scope_. Therefore, a program like this is illegal (and would be
+rejected by the compiler):
+
+~~~ {.xfail-test}
+fn example3() -> int {
+    let mut x = ~X {f: 3};
+    let y = &x.f;
+    x = ~X {f: 4};  // Error reported here.
+    *y
+}
+~~~
+
+To make this clearer, consider this diagram showing the state of
+memory immediately before the re-assignment of `x`:
+
+~~~ {.notrust}
+    Stack               Exchange Heap
+
+  x +----------+
+    | ~{f:int} | ----+
+  y +----------+     |
+    | &int     | ----+
+    +----------+     |    +---------+
+                     +--> |  f: 3   |
+                          +---------+
+~~~
+
+Once the reassignment occurs, the memory will look like this:
+
+~~~ {.notrust}
+    Stack               Exchange Heap
+
+  x +----------+          +---------+
+    | ~{f:int} | -------> |  f: 4   |
+  y +----------+          +---------+
+    | &int     | ----+
+    +----------+     |    +---------+
+                     +--> | (freed) |
+                          +---------+
+~~~
+
+Here you can see that the variable `y` still points at the old box,
+which has been freed.
+
+In fact, the compiler can apply the same kind of reasoning to any
+memory that is _(uniquely) owned by the stack frame_. So we could
+modify the previous example to introduce additional owned pointers
+and structs, and the compiler will still be able to detect possible
+mutations:
+
+~~~ {.xfail-test}
+fn example3() -> int {
+    struct R { g: int }
+    struct S { f: ~R }
+
+    let mut x = ~S {f: ~R {g: 3}};
+    let y = &x.f.g;
+    x = ~S {f: ~R {g: 4}};  // Error reported here.
+    x.f = ~R {g: 5};        // Error reported here.
+    *y
+}
+~~~
+
+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`.
+
+# Borrowing and enums
+
+The previous example showed that the type system forbids any borrowing
+of owned boxes found in aliasable, mutable memory. This restriction
+prevents pointers from pointing into freed memory. There is one other
+case where the compiler must be very careful to ensure that pointers
+remain valid: pointers into the interior of an `enum`.
+
+As an example, let’s look at the following `shape` type that can
+represent both rectangles and circles:
+
+~~~
+struct Point {x: f64, y: f64}; // as before
+struct Size {w: f64, h: f64}; // as before
+enum Shape {
+    Circle(Point, f64),   // origin, radius
+    Rectangle(Point, Size)  // upper-left, dimensions
+}
+~~~
+
+Now we might write a function to compute the area of a shape. This
+function takes a borrowed pointer to a shape, to avoid the need for
+copying.
+
+~~~
+# struct Point {x: f64, y: f64}; // as before
+# struct Size {w: f64, h: f64}; // as before
+# enum Shape {
+#     Circle(Point, f64),   // origin, radius
+#     Rectangle(Point, Size)  // upper-left, dimensions
+# }
+# static tau: f64 = 6.28;
+fn compute_area(shape: &Shape) -> f64 {
+    match *shape {
+        Circle(_, radius) => 0.5 * tau * radius * radius,
+        Rectangle(_, ref size) => size.w * size.h
+    }
+}
+~~~
+
+The first case matches against circles. Here, the pattern extracts the
+radius from the shape variant and the action uses it to compute the
+area of the circle. (Like any up-to-date engineer, we use the [tau
+circle constant][tau] and not that dreadfully outdated notion of pi).
+
+[tau]: http://www.math.utah.edu/~palais/pi.html
+
+The second match is more interesting. Here we match against a
+rectangle and extract its size: but rather than copy the `size`
+struct, we use a by-reference binding to create a pointer to it. In
+other words, a pattern binding like `ref size` binds the name `size`
+to a pointer of type `&size` into the _interior of the enum_.
+
+To make this more clear, let's look at a diagram of memory layout in
+the case where `shape` points at a rectangle:
+
+~~~ {.notrust}
+Stack             Memory
+
++-------+         +---------------+
+| shape | ------> | rectangle(    |
++-------+         |   {x: f64,    |
+| size  | -+      |    y: f64},   |
++-------+  +----> |   {w: f64,    |
+                  |    h: f64})   |
+                  +---------------+
+~~~
+
+Here you can see that rectangular shapes are composed of five words of
+memory. The first is a tag indicating which variant this enum is
+(`rectangle`, in this case). The next two words are the `x` and `y`
+fields for the point and the remaining two are the `w` and `h` fields
+for the size. The binding `size` is then a pointer into the inside of
+the shape.
+
+Perhaps you can see where the danger lies: if the shape were somehow
+to be reassigned, perhaps to a circle, then although the memory used
+to store that shape value would still be valid, _it would have a
+different type_! The following diagram shows what memory would look
+like if code overwrote `shape` with a circle:
+
+~~~ {.notrust}
+Stack             Memory
+
++-------+         +---------------+
+| shape | ------> | circle(       |
++-------+         |   {x: f64,    |
+| size  | -+      |    y: f64},   |
++-------+  +----> |   f64)        |
+                  |               |
+                  +---------------+
+~~~
+
+As you can see, the `size` pointer would be pointing at a `f64`
+instead of a struct. This is not good: dereferencing the second field
+of a `f64` as if it were a struct with two fields would be a memory
+safety violation.
+
+So, in fact, for every `ref` binding, the compiler will impose the
+same rules as the ones we saw for borrowing the interior of a owned
+box: it must be able to guarantee that the `enum` will not be
+overwritten for the duration of the borrow.  In fact, the compiler
+would accept the example we gave earlier. The example is safe because
+the shape pointer has type `&Shape`, which means "borrowed pointer to
+immutable memory containing a `shape`". If, however, the type of that
+pointer were `&mut Shape`, then the ref binding would be ill-typed.
+Just as with owned boxes, the compiler will 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.
+
+# Returning borrowed pointers
+
+So far, all of the examples we have looked at, use borrowed pointers in a
+“downward” direction. That is, a method or code block creates a
+borrowed pointer, then uses it within the same scope. It is also
+possible to return borrowed pointers as the result of a function, but
+as we'll see, doing so requires some explicit annotation.
+
+For example, we could write a subroutine like this:
+
+~~~
+struct Point {x: f64, y: f64}
+fn get_x<'r>(p: &'r Point) -> &'r f64 { &p.x }
+~~~
+
+Here, the function `get_x()` returns a pointer into the structure it
+was given. The type of the parameter (`&'r Point`) and return type
+(`&'r f64`) both use a new syntactic form that we have not seen so
+far.  Here the identifier `r` names the lifetime of the pointer
+explicitly. So in effect, this function declares that it takes a
+pointer with lifetime `r` and returns a pointer with that same
+lifetime.
+
+In general, it is only possible to return borrowed pointers if they
+are derived from a parameter to the procedure. In that case, the
+pointer result will always have the same lifetime as one of the
+parameters; named lifetimes indicate which parameter that
+is.
+
+In the previous examples, function parameter types did not include a
+lifetime name. In those examples, the compiler simply creates a fresh
+name for the lifetime automatically: that is, the lifetime name is
+guaranteed to refer to a distinct lifetime from the lifetimes of all
+other parameters.
+
+Named lifetimes that appear in function signatures are conceptually
+the same as the other lifetimes we have seen before, but they are a bit
+abstract: they don’t refer to a specific expression within `get_x()`,
+but rather to some expression within the *caller of `get_x()`*.  The
+lifetime `r` is actually a kind of *lifetime parameter*: it is defined
+by the caller to `get_x()`, just as the value for the parameter `p` is
+defined by that caller.
+
+In any case, whatever the lifetime of `r` is, the pointer produced by
+`&p.x` always has the same lifetime as `p` itself: a pointer to a
+field of a struct is valid as long as the struct is valid. Therefore,
+the compiler accepts the function `get_x()`.
+
+To emphasize this point, let’s look at a variation on the example, this
+time one that does not compile:
+
+~~~ {.xfail-test}
+struct Point {x: f64, y: f64}
+fn get_x_sh(p: @Point) -> &f64 {
+    &p.x // Error reported here
+}
+~~~
+
+Here, the function `get_x_sh()` takes a managed box as input and
+returns a borrowed pointer. As before, the lifetime of the borrowed
+pointer that will be returned is a parameter (specified by the
+caller). That means that `get_x_sh()` promises to return a borrowed
+pointer that is valid for as long as the caller would like: this is
+subtly different from the first example, which promised to return a
+pointer that was valid for as long as its pointer argument was valid.
+
+Within `get_x_sh()`, we see the expression `&p.x` which takes the
+address of a field of a managed box. The presence of this expression
+implies that the compiler must guarantee that, so long as the
+resulting pointer is valid, the managed box will not be reclaimed by
+the garbage collector. But recall that `get_x_sh()` also promised to
+return a pointer that was valid for as long as the caller wanted it to
+be. Clearly, `get_x_sh()` is not in a position to make both of these
+guarantees; in fact, it cannot guarantee that the pointer will remain
+valid at all once it returns, as the parameter `p` may or may not be
+live in the caller. Therefore, the compiler will report an error here.
+
+In general, if you borrow a managed (or owned) box to create a
+borrowed pointer, the pointer will only be valid within the function
+and cannot be returned. This is why the typical way to return borrowed
+pointers is to take borrowed pointers as input (the only other case in
+which it can be legal to return a borrowed pointer is if the pointer
+points at a static constant).
+
+# Named lifetimes
+
+Let's look at named lifetimes in more detail. Named lifetimes allow
+for grouping of parameters by lifetime. For example, consider this
+function:
+
+~~~
+# struct Point {x: f64, y: f64}; // as before
+# struct Size {w: f64, h: f64}; // as before
+# enum Shape {
+#     Circle(Point, f64),   // origin, radius
+#     Rectangle(Point, Size)  // upper-left, dimensions
+# }
+# fn compute_area(shape: &Shape) -> f64 { 0.0 }
+fn select<'r, T>(shape: &'r Shape, threshold: f64,
+                 a: &'r T, b: &'r T) -> &'r T {
+    if compute_area(shape) > threshold {a} else {b}
+}
+~~~
+
+This function takes three borrowed pointers and assigns each the same
+lifetime `r`.  In practice, this means that, in the caller, the
+lifetime `r` will be the *intersection of the lifetime of the three
+region parameters*. This may be overly conservative, as in this
+example:
+
+~~~
+# struct Point {x: f64, y: f64}; // as before
+# struct Size {w: f64, h: f64}; // as before
+# enum Shape {
+#     Circle(Point, f64),   // origin, radius
+#     Rectangle(Point, Size)  // upper-left, dimensions
+# }
+# fn compute_area(shape: &Shape) -> f64 { 0.0 }
+# fn select<'r, T>(shape: &Shape, threshold: f64,
+#                  a: &'r T, b: &'r T) -> &'r T {
+#     if compute_area(shape) > threshold {a} else {b}
+# }
+                                                     // -+ r
+fn select_based_on_unit_circle<'r, T>(               //  |-+ B
+    threshold: f64, a: &'r T, b: &'r T) -> &'r T { //  | |
+                                                     //  | |
+    let shape = Circle(Point {x: 0., y: 0.}, 1.);    //  | |
+    select(&shape, threshold, a, b)                  //  | |
+}                                                    //  |-+
+                                                     // -+
+~~~
+
+In this call to `select()`, the lifetime of the first parameter shape
+is B, the function body. Both of the second two parameters `a` and `b`
+share the same lifetime, `r`, which is a lifetime parameter of
+`select_based_on_unit_circle()`. The caller will infer the
+intersection of these two lifetimes as the lifetime of the returned
+value, and hence the return value of `select()` will be assigned a
+lifetime of B. This will in turn lead to a compilation error, because
+`select_based_on_unit_circle()` is supposed to return a value with the
+lifetime `r`.
+
+To address this, we can modify the definition of `select()` to
+distinguish the lifetime of the first parameter from the lifetime of
+the latter two. After all, the first parameter is not being
+returned. Here is how the new `select()` might look:
+
+~~~
+# struct Point {x: f64, y: f64}; // as before
+# struct Size {w: f64, h: f64}; // as before
+# enum Shape {
+#     Circle(Point, f64),   // origin, radius
+#     Rectangle(Point, Size)  // upper-left, dimensions
+# }
+# fn compute_area(shape: &Shape) -> f64 { 0.0 }
+fn select<'r, 'tmp, T>(shape: &'tmp Shape, threshold: f64,
+                       a: &'r T, b: &'r T) -> &'r T {
+    if compute_area(shape) > threshold {a} else {b}
+}
+~~~
+
+Here you can see that `shape`'s lifetime is now named `tmp`. The
+parameters `a`, `b`, and the return value all have the lifetime `r`.
+However, since the lifetime `tmp` is not returned, it would be more
+concise to just omit the named lifetime for `shape` altogether:
+
+~~~
+# struct Point {x: f64, y: f64}; // as before
+# struct Size {w: f64, h: f64}; // as before
+# enum Shape {
+#     Circle(Point, f64),   // origin, radius
+#     Rectangle(Point, Size)  // upper-left, dimensions
+# }
+# fn compute_area(shape: &Shape) -> f64 { 0.0 }
+fn select<'r, T>(shape: &Shape, threshold: f64,
+                 a: &'r T, b: &'r T) -> &'r T {
+    if compute_area(shape) > threshold {a} else {b}
+}
+~~~
+
+This is equivalent to the previous definition.
+
+# Conclusion
+
+So there you have it: a (relatively) brief tour of the borrowed pointer
+system. For more details, we refer to the (yet to be written) reference
+document on borrowed pointers, which will explain the full notation
+and give more examples.
diff --git a/doc/guide-conditions.md b/doc/guide-conditions.md
new file mode 100644 (file)
index 0000000..5f27888
--- /dev/null
@@ -0,0 +1,858 @@
+% Rust Condition and Error-handling Guide
+
+# Introduction
+
+Rust does not provide exception handling[^why-no-exceptions]
+in the form most commonly seen in other programming languages such as C++ or Java.
+Instead, it provides four mechanisms that work together to handle errors or other rare events.
+The four mechanisms are:
+
+  - Options
+  - Results
+  - Failure
+  - Conditions
+
+This guide will lead you through use of these mechanisms
+in order to understand the trade-offs of each and relationships between them.
+
+# Example program
+
+This guide will be based around an example program
+that attempts to read lines from a file
+consisting of pairs of numbers,
+and then print them back out with slightly different formatting.
+The input to the program might look like this:
+
+~~~~ {.notrust}
+$ cat numbers.txt
+1 2
+34 56
+789 123
+45 67
+~~~~
+
+For which the intended output looks like this:
+
+~~~~ {.notrust}
+$ ./example numbers.txt
+0001, 0002
+0034, 0056
+0789, 0123
+0045, 0067
+~~~~
+
+An example program that does this task reads like this:
+
+~~~~
+# #[allow(unused_imports)];
+# extern mod extra;
+use std::io::buffered::BufferedReader;
+use std::io::File;
+# mod BufferedReader {
+#     use std::io::File;
+#     use std::io::mem::MemReader;
+#     use std::io::buffered::BufferedReader;
+#     static s : &'static [u8] = bytes!("1 2\n\
+#                                        34 56\n\
+#                                        789 123\n\
+#                                        45 67\n\
+#                                        ");
+#     pub fn new(_inner: Option<File>) -> BufferedReader<MemReader> {
+#           BufferedReader::new(MemReader::new(s.to_owned()))
+#     }
+# }
+
+fn main() {
+    let pairs = read_int_pairs();
+    for &(a,b) in pairs.iter() {
+        println!("{:4.4d}, {:4.4d}", a, b);
+    }
+}
+
+fn read_int_pairs() -> ~[(int,int)] {
+    let mut pairs = ~[];
+
+    // Path takes a generic by-value, rather than by reference
+#    let _g = std::io::ignore_io_error();
+    let path = Path::new(&"foo.txt");
+    let mut reader = BufferedReader::new(File::open(&path));
+
+    // 1. Iterate over the lines of our file.
+    for line in reader.lines() {
+        // 2. Split the line into fields ("words").
+        let fields = line.words().to_owned_vec();
+        // 3. Match the vector of fields against a vector pattern.
+        match fields {
+
+            // 4. When the line had two fields:
+            [a, b] => {
+                // 5. Try parsing both fields as ints.
+                match (from_str::<int>(a), from_str::<int>(b)) {
+
+                    // 6. If parsing succeeded for both, push both.
+                    (Some(a), Some(b)) => pairs.push((a,b)),
+                    // 7. Ignore non-int fields.
+                    _ => ()
+                }
+            }
+            // 8. Ignore lines that don't have 2 fields.
+            _ => ()
+        }
+    }
+    pairs
+}
+~~~~
+
+This example shows the use of `Option`,
+along with some other forms of error-handling (and non-handling).
+We will look at these mechanisms
+and then modify parts of the example to perform "better" error handling.
+
+# Options
+
+The simplest and most lightweight mechanism in Rust for indicating an error is the type `std::option::Option<T>`.
+This type is a general purpose `enum`
+for conveying a value of type `T`, represented as `Some(T)`
+_or_ the sentinel `None`, to indicate the absence of a `T` value.
+For simple APIs, it may be sufficient to encode errors as `Option<T>`,
+returning `Some(T)` on success and `None` on error.
+In the example program, the call to `from_str::<int>` returns `Option<int>`
+with the understanding that "all parse errors" result in `None`.
+The resulting `Option<int>` values are matched against the pattern `(Some(a), Some(b))`
+in steps 5 and 6 in the example program,
+to handle the case in which both fields were parsed successfully.
+
+Using `Option` as in this API has some advantages:
+
+  - Simple API, users can read it and guess how it works.
+  - Very efficient, only an extra `enum` tag on return values.
+  - Caller has flexibility in handling or propagating errors.
+  - Caller is forced to acknowledge existence of possible-error before using value.
+
+However, it has serious disadvantages too:
+
+  - Verbose, requires matching results or calling `Option::unwrap` everywhere.
+  - Infects caller: if caller doesn't know how to handle the error, must propagate (or force).
+  - Temptation to do just that: force the `Some(T)` case by blindly calling `unwrap`,
+    which hides the error from the API without providing any way to make the program robust against the error.
+  - Collapses all errors into one:
+    - Caller can't handle different errors differently.
+    - Caller can't even report a very precise error message
+
+Note that in order to keep the example code reasonably compact,
+several unwanted cases are silently ignored:
+lines that do not contain two fields, as well as fields that do not parse as ints.
+To propagate these cases to the caller using `Option` would require even more verbose code.
+
+# Results
+
+Before getting into _trapping_ the error,
+we will look at a slight refinement on the `Option` type above.
+This second mechanism for indicating an error is called a `Result`.
+The type `std::result::Result<T,E>` is another simple `enum` type with two forms, `Ok(T)` and `Err(E)`.
+The `Result` type is not substantially different from the `Option` type in terms of its ergonomics.
+Its main advantage is that the error constructor `Err(E)` can convey _more detail_ about the error.
+For example, the `from_str` API could be reformed
+to return a `Result` carrying an informative description of a parse error,
+like this:
+
+~~~~ {.ignore}
+enum IntParseErr {
+     EmptyInput,
+     Overflow,
+     BadChar(char)
+}
+
+fn from_str(&str) -> Result<int,IntParseErr> {
+  // ...
+}
+~~~~
+
+This would give the caller more information for both handling and reporting the error,
+but would otherwise retain the verbosity problems of using `Option`.
+In particular, it would still be necessary for the caller to return a further `Result` to _its_ caller if it did not want to handle the error.
+Manually propagating result values this way can be attractive in certain circumstances
+&mdash; for example when processing must halt on the very first error, or backtrack &mdash;
+but as we will see later, many cases have simpler options available.
+
+# Failure
+
+The third and arguably easiest mechanism for handling errors is called "failure".
+In fact it was hinted at earlier by suggesting that one can choose to propagate `Option` or `Result` types _or "force" them_.
+"Forcing" them, in this case, means calling a method like `Option<T>::unwrap`,
+which contains the following code:
+
+~~~~ {.ignore}
+pub fn unwrap(self) -> T {
+    match self {
+      Some(x) => return x,
+      None => fail!("option::unwrap `None`")
+    }
+}
+~~~~
+
+That is, it returns `T` when `self` is `Some(T)`, and  _fails_ when `self` is `None`.
+
+Every Rust task can _fail_, either indirectly due to a kill signal or other asynchronous event,
+or directly by failing an `assert!` or calling the `fail!` macro.
+Failure is an _unrecoverable event_ at the task level:
+it causes the task to halt normal execution and unwind its control stack,
+freeing all task-local resources (the local heap as well as any task-owned values from the global heap)
+and running destructors (the `drop` method of the `Drop` trait)
+as frames are unwound and heap values destroyed.
+A failing task is not permitted to "catch" the unwinding during failure and recover,
+it is only allowed to clean up and exit.
+
+Failure has advantages:
+
+  - Simple and non-verbose. Suitable for programs that can't reasonably continue past an error anyways.
+  - _All_ errors (except memory-safety errors) can be uniformly trapped in a supervisory task outside the failing task.
+    For a large program to be robust against a variety of errors,
+    often some form of task-level partitioning to contain pervasive errors (arithmetic overflow, division by zero,
+    logic bugs) is necessary anyways.
+
+As well as obvious disadvantages:
+
+  - A blunt instrument, terminates the containing task entirely.
+
+Recall that in the first two approaches to error handling,
+the example program was only handling success cases, and ignoring error cases.
+That is, if the input is changed to contain a malformed line:
+
+~~~~ {.notrust}
+$ cat bad.txt
+1 2
+34 56
+ostrich
+789 123
+45 67
+~~~~
+
+Then the program would give the same output as if there was no error:
+
+~~~~ {.notrust}
+$ ./example bad.txt
+0001, 0002
+0034, 0056
+0789, 0123
+0045, 0067
+~~~~
+
+If the example is rewritten to use failure, these error cases can be trapped.
+In this rewriting, failures are trapped by placing the I/O logic in a sub-task,
+and trapping its exit status using `task::try`:
+
+~~~~
+# #[allow(unused_imports)];
+# extern mod extra;
+use std::io::buffered::BufferedReader;
+use std::io::File;
+use std::task;
+# mod BufferedReader {
+#     use std::io::File;
+#     use std::io::mem::MemReader;
+#     use std::io::buffered::BufferedReader;
+#     static s : &'static [u8] = bytes!("1 2\n\
+#                                        34 56\n\
+#                                        789 123\n\
+#                                        45 67\n\
+#                                        ");
+#     pub fn new(_inner: Option<File>) -> BufferedReader<MemReader> {
+#           BufferedReader::new(MemReader::new(s.to_owned()))
+#     }
+# }
+
+fn main() {
+
+    // Isolate failure within a subtask.
+    let result = do task::try {
+
+        // The protected logic.
+        let pairs = read_int_pairs();
+        for &(a,b) in pairs.iter() {
+            println!("{:4.4d}, {:4.4d}", a, b);
+        }
+
+    };
+    if result.is_err() {
+            println("parsing failed");
+    }
+}
+
+fn read_int_pairs() -> ~[(int,int)] {
+    let mut pairs = ~[];
+#    let _g = std::io::ignore_io_error();
+    let path = Path::new(&"foo.txt");
+
+    let mut reader = BufferedReader::new(File::open(&path));
+    for line in reader.lines() {
+        match line.words().to_owned_vec() {
+            [a, b] => pairs.push((from_str::<int>(a).unwrap(),
+                                  from_str::<int>(b).unwrap())),
+
+            // Explicitly fail on malformed lines.
+            _ => fail!()
+        }
+    }
+    pairs
+}
+~~~~
+
+With these changes in place, running the program on malformed input gives a different answer:
+
+~~~~ {.notrust}
+$ ./example bad.txt
+rust: task failed at 'explicit failure', ./example.rs:44
+parsing failed
+~~~~
+
+Note that while failure unwinds the sub-task performing I/O in `read_int_pairs`,
+control returns to `main` and can easily continue uninterrupted.
+In this case, control simply prints out `parsing failed` and then exits `main` (successfully).
+Failure of a (sub-)task is analogous to calling `exit(1)` or `abort()` in a unix C program:
+all the state of a sub-task is cleanly discarded on exit,
+and a supervisor task can take appropriate action
+without worrying about its own state having been corrupted.
+
+# Conditions
+
+The final mechanism for handling errors is called a "condition".
+Conditions are less blunt than failure, and less cumbersome than the `Option` or `Result` types;
+indeed they are designed to strike just the right balance between the two.
+Conditions require some care to use effectively, but give maximum flexibility with minimum verbosity.
+While conditions use exception-like terminology ("trap", "raise") they are significantly different:
+
+  - Like exceptions and failure, conditions separate the site at which the error is raised from the site where it is trapped.
+  - Unlike exceptions and unlike failure, when a condition is raised and trapped, _no unwinding occurs_.
+  - A successfully trapped condition causes execution to continue _at the site of the error_, as though no error occurred.
+
+Conditions are declared with the `condition!` macro.
+Each condition has a name, an input type and an output type, much like a function.
+In fact, conditions are implemented as dynamically-scoped functions held in task local storage.
+
+The `condition!` macro declares a module with the name of the condition;
+the module contains a single static value called `cond`, of type `std::condition::Condition`.
+The `cond` value within the module is the rendezvous point
+between the site of error and the site that handles the error.
+It has two methods of interest: `raise` and `trap`.
+
+The `raise` method maps a value of the condition's input type to its output type.
+The input type should therefore convey all relevant information to the condition handler.
+The output type should convey all relevant information _for continuing execution at the site of error_.
+When the error site raises a condition handler,
+the `Condition::raise` method searches for the innermost installed task-local condition _handler_,
+and if any such handler is found, calls it with the provided input value.
+If no handler is found, `Condition::raise` will fail the task with an appropriate error message.
+
+Rewriting the example to use a condition in place of ignoring malformed lines makes it slightly longer,
+but similarly clear as the version that used `fail!` in the logic where the error occurs:
+
+~~~~
+# #[allow(unused_imports)];
+# extern mod extra;
+use std::io::buffered::BufferedReader;
+use std::io::File;
+# mod BufferedReader {
+#     use std::io::File;
+#     use std::io::mem::MemReader;
+#     use std::io::buffered::BufferedReader;
+#     static s : &'static [u8] = bytes!("1 2\n\
+#                                        34 56\n\
+#                                        789 123\n\
+#                                        45 67\n\
+#                                        ");
+#     pub fn new(_inner: Option<File>) -> BufferedReader<MemReader> {
+#           BufferedReader::new(MemReader::new(s.to_owned()))
+#     }
+# }
+
+// Introduce a new condition.
+condition! {
+    pub malformed_line : ~str -> (int,int);
+}
+
+fn main() {
+    let pairs = read_int_pairs();
+    for &(a,b) in pairs.iter() {
+        println!("{:4.4d}, {:4.4d}", a, b);
+    }
+}
+
+fn read_int_pairs() -> ~[(int,int)] {
+    let mut pairs = ~[];
+#    let _g = std::io::ignore_io_error();
+    let path = Path::new(&"foo.txt");
+
+    let mut reader = BufferedReader::new(File::open(&path));
+    for line in reader.lines() {
+        match line.words().to_owned_vec() {
+            [a, b] => pairs.push((from_str::<int>(a).unwrap(),
+                                  from_str::<int>(b).unwrap())),
+            // On malformed lines, call the condition handler and
+            // push whatever the condition handler returns.
+            _ => pairs.push(malformed_line::cond.raise(line.clone()))
+        }
+    }
+    pairs
+}
+~~~~
+
+When this is run on malformed input, it still fails,
+but with a slightly different failure message than before:
+
+~~~~ {.notrust}
+$ ./example bad.txt
+rust: task failed at 'Unhandled condition: malformed_line: ~"ostrich"', .../libstd/condition.rs:43
+~~~~
+
+While this superficially resembles the trapped `fail!` call before,
+it is only because the example did not install a handler for the condition.
+The different failure message is indicating, among other things,
+that the condition-handling system is being invoked and failing
+only due to the absence of a _handler_ that traps the condition.
+
+# Trapping a condition
+
+To trap a condition, use `Condition::trap` in some caller of the site that calls `Condition::raise`.
+For example, this version of the program traps the `malformed_line` condition
+and replaces bad input lines with the pair `(-1,-1)`:
+
+~~~~
+# #[allow(unused_imports)];
+# extern mod extra;
+use std::io::buffered::BufferedReader;
+use std::io::File;
+# mod BufferedReader {
+#     use std::io::File;
+#     use std::io::mem::MemReader;
+#     use std::io::buffered::BufferedReader;
+#     static s : &'static [u8] = bytes!("1 2\n\
+#                                        34 56\n\
+#                                        789 123\n\
+#                                        45 67\n\
+#                                        ");
+#     pub fn new(_inner: Option<File>) -> BufferedReader<MemReader> {
+#           BufferedReader::new(MemReader::new(s.to_owned()))
+#     }
+# }
+
+condition! {
+    pub malformed_line : ~str -> (int,int);
+}
+
+fn main() {
+    // Trap the condition:
+    malformed_line::cond.trap(|_| (-1,-1)).inside(|| {
+
+        // The protected logic.
+        let pairs = read_int_pairs();
+        for &(a,b) in pairs.iter() {
+                println!("{:4.4d}, {:4.4d}", a, b);
+        }
+
+    })
+}
+
+fn read_int_pairs() -> ~[(int,int)] {
+    let mut pairs = ~[];
+#    let _g = std::io::ignore_io_error();
+    let path = Path::new(&"foo.txt");
+
+    let mut reader = BufferedReader::new(File::open(&path));
+    for line in reader.lines() {
+        match line.words().to_owned_vec() {
+            [a, b] => pairs.push((from_str::<int>(a).unwrap(),
+                                  from_str::<int>(b).unwrap())),
+            _ => pairs.push(malformed_line::cond.raise(line.clone()))
+        }
+    }
+    pairs
+}
+~~~~
+
+Note that the remainder of the program is _unchanged_ with this trap in place;
+only the caller that installs the trap changed.
+Yet when the condition-trapping variant runs on the malformed input,
+it continues execution past the malformed line, substituting the handler's return value.
+
+~~~~ {.notrust}
+$ ./example bad.txt
+0001, 0002
+0034, 0056
+-0001, -0001
+0789, 0123
+0045, 0067
+~~~~
+
+# Refining a condition
+
+As you work with a condition, you may find that the original set of options you present for recovery is insufficient.
+This is no different than any other issue of API design:
+a condition handler is an API for recovering from the condition, and sometimes APIs need to be enriched.
+In the example program, the first form of the `malformed_line` API implicitly assumes that recovery involves a substitute value.
+This assumption may not be correct; some callers may wish to skip malformed lines, for example.
+Changing the condition's return type from `(int,int)` to `Option<(int,int)>` will suffice to support this type of recovery:
+
+~~~~
+# #[allow(unused_imports)];
+# extern mod extra;
+use std::io::buffered::BufferedReader;
+use std::io::File;
+# mod BufferedReader {
+#     use std::io::File;
+#     use std::io::mem::MemReader;
+#     use std::io::buffered::BufferedReader;
+#     static s : &'static [u8] = bytes!("1 2\n\
+#                                        34 56\n\
+#                                        789 123\n\
+#                                        45 67\n\
+#                                        ");
+#     pub fn new(_inner: Option<File>) -> BufferedReader<MemReader> {
+#           BufferedReader::new(MemReader::new(s.to_owned()))
+#     }
+# }
+
+// Modify the condition signature to return an Option.
+condition! {
+    pub malformed_line : ~str -> Option<(int,int)>;
+}
+
+fn main() {
+    // Trap the condition and return `None`
+    malformed_line::cond.trap(|_| None).inside(|| {
+
+        // The protected logic.
+        let pairs = read_int_pairs();
+        for &(a,b) in pairs.iter() {
+            println!("{:4.4d}, {:4.4d}", a, b);
+        }
+
+    })
+}
+
+fn read_int_pairs() -> ~[(int,int)] {
+    let mut pairs = ~[];
+#    let _g = std::io::ignore_io_error();
+    let path = Path::new(&"foo.txt");
+
+    let mut reader = BufferedReader::new(File::open(&path));
+    for line in reader.lines() {
+        match line.words().to_owned_vec() {
+            [a, b] => pairs.push((from_str::<int>(a).unwrap(),
+                                  from_str::<int>(b).unwrap())),
+
+            // On malformed lines, call the condition handler and
+            // either ignore the line (if the handler returns `None`)
+            // or push any `Some(pair)` value returned instead.
+            _ => {
+                match malformed_line::cond.raise(line.clone()) {
+                    Some(pair) => pairs.push(pair),
+                    None => ()
+                }
+            }
+        }
+    }
+    pairs
+}
+~~~~
+
+Again, note that the remainder of the program is _unchanged_,
+in particular the signature of `read_int_pairs` is unchanged,
+even though the innermost part of its reading-loop has a new way of handling a malformed line.
+When the example is run with the `None` trap in place,
+the line is ignored as it was in the first example,
+but the choice of whether to ignore or use a substitute value has been moved to some caller,
+possibly a distant caller.
+
+~~~~ {.notrust}
+$ ./example bad.txt
+0001, 0002
+0034, 0056
+0789, 0123
+0045, 0067
+~~~~
+
+# Further refining a condition
+
+Like with any API, the process of refining argument and return types of a condition will continue,
+until all relevant combinations encountered in practice are encoded.
+In the example, suppose a third possible recovery form arose: reusing the previous value read.
+This can be encoded in the handler API by introducing a helper type: `enum MalformedLineFix`.
+
+~~~~
+# #[allow(unused_imports)];
+# extern mod extra;
+use std::io::buffered::BufferedReader;
+use std::io::File;
+# mod BufferedReader {
+#     use std::io::File;
+#     use std::io::mem::MemReader;
+#     use std::io::buffered::BufferedReader;
+#     static s : &'static [u8] = bytes!("1 2\n\
+#                                        34 56\n\
+#                                        789 123\n\
+#                                        45 67\n\
+#                                        ");
+#     pub fn new(_inner: Option<File>) -> BufferedReader<MemReader> {
+#           BufferedReader::new(MemReader::new(s.to_owned()))
+#     }
+# }
+
+// Introduce a new enum to convey condition-handling strategy to error site.
+pub enum MalformedLineFix {
+     UsePair(int,int),
+     IgnoreLine,
+     UsePreviousLine
+}
+
+// Modify the condition signature to return the new enum.
+// Note: a condition introduces a new module, so the enum must be
+// named with the `super::` prefix to access it.
+condition! {
+    pub malformed_line : ~str -> super::MalformedLineFix;
+}
+
+fn main() {
+    // Trap the condition and return `UsePreviousLine`
+    malformed_line::cond.trap(|_| UsePreviousLine).inside(|| {
+
+        // The protected logic.
+        let pairs = read_int_pairs();
+        for &(a,b) in pairs.iter() {
+            println!("{:4.4d}, {:4.4d}", a, b);
+        }
+
+    })
+}
+
+fn read_int_pairs() -> ~[(int,int)] {
+    let mut pairs = ~[];
+#    let _g = std::io::ignore_io_error();
+    let path = Path::new(&"foo.txt");
+
+    let mut reader = BufferedReader::new(File::open(&path));
+    for line in reader.lines() {
+        match line.words().to_owned_vec() {
+            [a, b] => pairs.push((from_str::<int>(a).unwrap(),
+                                  from_str::<int>(b).unwrap())),
+
+            // On malformed lines, call the condition handler and
+            // take action appropriate to the enum value returned.
+            _ => {
+                match malformed_line::cond.raise(line.clone()) {
+                    UsePair(a,b) => pairs.push((a,b)),
+                    IgnoreLine => (),
+                    UsePreviousLine => {
+                        let prev = pairs[pairs.len() - 1];
+                        pairs.push(prev)
+                    }
+                }
+            }
+        }
+    }
+    pairs
+}
+~~~~
+
+Running the example with `UsePreviousLine` as the fix code returned from the handler
+gives the expected result:
+
+~~~~ {.notrust}
+$ ./example bad.txt
+0001, 0002
+0034, 0056
+0034, 0056
+0789, 0123
+0045, 0067
+~~~~
+
+At this point the example has a rich variety of recovery options,
+none of which is visible to casual users of the `read_int_pairs` function.
+This is intentional: part of the purpose of using a condition
+is to free intermediate callers from the burden of having to write repetitive error-propagation logic,
+and/or having to change function call and return types as error-handling strategies are refined.
+
+# Multiple conditions, intermediate callers
+
+So far the function trapping the condition and the function raising it have been immediately adjacent in the call stack.
+That is, the caller traps and its immediate callee raises.
+In most programs, the function that traps may be separated by very many function calls from the function that raises.
+Again, this is part of the point of using conditions:
+to support that separation without having to thread multiple error values and recovery strategies all the way through the program's main logic.
+
+Careful readers will notice that there is a remaining failure mode in the example program: the call to `.unwrap()` when parsing each integer.
+For example, when presented with a file that has the correct number of fields on a line,
+but a non-numeric value in one of them, such as this:
+
+~~~~ {.notrust}
+$ cat bad.txt
+1 2
+34 56
+7 marmot
+789 123
+45 67
+~~~~
+
+
+Then the program fails once more:
+
+~~~~ {.notrust}
+$ ./example bad.txt
+task <unnamed> failed at 'called `Option::unwrap()` on a `None` value', .../libstd/option.rs:314
+~~~~
+
+To make the program robust &mdash; or at least flexible &mdash; in the face of this potential failure,
+a second condition and a helper function will suffice:
+
+~~~~
+# #[allow(unused_imports)];
+# extern mod extra;
+use std::io::buffered::BufferedReader;
+use std::io::File;
+# mod BufferedReader {
+#     use std::io::File;
+#     use std::io::mem::MemReader;
+#     use std::io::buffered::BufferedReader;
+#     static s : &'static [u8] = bytes!("1 2\n\
+#                                        34 56\n\
+#                                        789 123\n\
+#                                        45 67\n\
+#                                        ");
+#     pub fn new(_inner: Option<File>) -> BufferedReader<MemReader> {
+#           BufferedReader::new(MemReader::new(s.to_owned()))
+#     }
+# }
+
+pub enum MalformedLineFix {
+     UsePair(int,int),
+     IgnoreLine,
+     UsePreviousLine
+}
+
+condition! {
+    pub malformed_line : ~str -> ::MalformedLineFix;
+}
+
+// Introduce a second condition.
+condition! {
+    pub malformed_int : ~str -> int;
+}
+
+fn main() {
+    // Trap the `malformed_int` condition and return -1
+    malformed_int::cond.trap(|_| -1).inside(|| {
+
+        // Trap the `malformed_line` condition and return `UsePreviousLine`
+        malformed_line::cond.trap(|_| UsePreviousLine).inside(|| {
+
+            // The protected logic.
+            let pairs = read_int_pairs();
+            for &(a,b) in pairs.iter() {
+                println!("{:4.4d}, {:4.4d}", a, b);
+            }
+
+        })
+    })
+}
+
+// Parse an int; if parsing fails, call the condition handler and
+// return whatever it returns.
+fn parse_int(x: &str) -> int {
+    match from_str::<int>(x) {
+        Some(v) => v,
+        None => malformed_int::cond.raise(x.to_owned())
+    }
+}
+
+fn read_int_pairs() -> ~[(int,int)] {
+    let mut pairs = ~[];
+#    let _g = std::io::ignore_io_error();
+    let path = Path::new(&"foo.txt");
+
+    let mut reader = BufferedReader::new(File::open(&path));
+    for line in reader.lines() {
+        match line.words().to_owned_vec() {
+            // Delegate parsing ints to helper function that will
+            // handle parse errors by calling `malformed_int`.
+            [a, b] => pairs.push((parse_int(a), parse_int(b))),
+
+            _ => {
+                match malformed_line::cond.raise(line.clone()) {
+                    UsePair(a,b) => pairs.push((a,b)),
+                    IgnoreLine => (),
+                    UsePreviousLine => {
+                        let prev = pairs[pairs.len() - 1];
+                        pairs.push(prev)
+                    }
+                }
+            }
+        }
+    }
+    pairs
+}
+~~~~
+
+Again, note that `read_int_pairs` has not changed signature,
+nor has any of the machinery for trapping or raising `malformed_line`,
+but now the program can handle the "right number of fields, non-integral field" form of bad input:
+
+~~~~ {.notrust}
+$ ./example bad.txt
+0001, 0002
+0034, 0056
+0007, -0001
+0789, 0123
+0045, 0067
+~~~~
+
+There are three other things to note in this variant of the example program:
+
+  - It traps multiple conditions simultaneously,
+    nesting the protected logic of one `trap` call inside the other.
+
+  - There is a function in between the `trap` site and `raise` site for the `malformed_int` condition.
+    There could be any number of calls between them:
+    so long as the `raise` occurs within a callee (of any depth) of the logic protected by the `trap` call,
+    it will invoke the handler.
+
+  - This variant insulates callers from a design choice in the library:
+    the `from_str` function was designed to return an `Option<int>`,
+    but this program insulates callers from that choice,
+    routing all `None` values that arise from parsing integers in this file into the condition.
+
+
+# When to use which technique
+
+This guide explored several techniques for handling errors.
+Each is appropriate to different circumstances:
+
+  - If an error may be extremely frequent, expected, and very likely dealt with by an immediate caller,
+    then returning an `Option` or `Result` type is best. These types force the caller to handle the error,
+    and incur the lowest speed overhead, usually only returning one extra word to tag the return value.
+    Between `Option` and `Result`: use an `Option` when there is only one kind of error,
+    otherwise make an `enum FooErr` to represent the possible error codes and use `Result<T,FooErr>`.
+
+  - If an error can reasonably be handled at the site it occurs by one of a few strategies &mdash; possibly including failure &mdash;
+    and it is not clear which strategy a caller would want to use, a condition is best.
+    For many errors, the only reasonable "non-stop" recovery strategies are to retry some number of times,
+    create or substitute an empty or sentinel value, ignore the error, or fail.
+
+  - If an error cannot reasonably be handled at the site it occurs,
+    and the only reasonable response is to abandon a large set of operations in progress,
+    then directly failing is best.
+
+Note that an unhandled condition will cause failure (along with a more-informative-than-usual message),
+so if there is any possibility that a caller might wish to "ignore and keep going",
+it is usually harmless to use a condition in place of a direct call to `fail!()`.
+
+
+[^why-no-exceptions]: Exceptions in languages like C++ and Java permit unwinding, like Rust's failure system,
+but with the option to halt unwinding partway through the process and continue execution.
+This behavior unfortunately means that the _heap_ may be left in an inconsistent but accessible state,
+if an exception is thrown part way through the process of initializing or modifying memory.
+To compensate for this risk, correct C++ and Java code must program in an extremely elaborate and difficult "exception-safe" style
+&mdash; effectively transactional style against heap structures &mdash;
+or else risk introducing silent and very difficult-to-debug errors due to control resuming in a corrupted heap after a caught exception.
+These errors are frequently memory-safety errors, which Rust strives to eliminate,
+and so Rust unwinding is unrecoverable within a single task:
+once unwinding starts, the entire local heap of a task is destroyed and the task is terminated.
diff --git a/doc/guide-container.md b/doc/guide-container.md
new file mode 100644 (file)
index 0000000..90a0160
--- /dev/null
@@ -0,0 +1,410 @@
+% Containers and Iterators Guide
+
+# Containers
+
+The container traits are defined in the `std::container` module.
+
+## Unique vectors
+
+Vectors have `O(1)` indexing, push (to the end) and pop (from the end). Vectors
+are the most common container in Rust, and are flexible enough to fit many use
+cases.
+
+Vectors can also be sorted and used as efficient lookup tables with the
+`bsearch()` method, if all the elements are inserted at one time and
+deletions are unnecessary.
+
+## Maps and sets
+
+Maps are collections of unique keys with corresponding values, and sets are
+just unique keys without a corresponding value. The `Map` and `Set` traits in
+`std::container` define the basic interface.
+
+The standard library provides three owned map/set types:
+
+* `std::hashmap::HashMap` and `std::hashmap::HashSet`, requiring the keys to
+  implement `Eq` and `Hash`
+* `std::trie::TrieMap` and `std::trie::TrieSet`, requiring the keys to be `uint`
+* `extra::treemap::TreeMap` and `extra::treemap::TreeSet`, requiring the keys
+  to implement `TotalOrd`
+
+These maps do not use managed pointers so they can be sent between tasks as
+long as the key and value types are sendable. Neither the key or value type has
+to be copyable.
+
+The `TrieMap` and `TreeMap` maps are ordered, while `HashMap` uses an arbitrary
+order.
+
+Each `HashMap` instance has a random 128-bit key to use with a keyed hash,
+making the order of a set of keys in a given hash table randomized. Rust
+provides a [SipHash](https://131002.net/siphash/) implementation for any type
+implementing the `IterBytes` trait.
+
+## Double-ended queues
+
+The `extra::ringbuf` module implements a double-ended queue with `O(1)`
+amortized inserts and removals from both ends of the container. It also has
+`O(1)` indexing like a vector. The contained elements are not required to be
+copyable, and the queue will be sendable if the contained type is sendable.
+Its interface `Deque` is defined in `extra::collections`.
+
+The `extra::dlist` module implements a double-ended linked list, also
+implementing the `Deque` trait, with `O(1)` removals and inserts at either end,
+and `O(1)` concatenation.
+
+## Priority queues
+
+The `extra::priority_queue` module implements a queue ordered by a key.  The
+contained elements are not required to be copyable, and the queue will be
+sendable if the contained type is sendable.
+
+Insertions have `O(log n)` time complexity and checking or popping the largest
+element is `O(1)`. Converting a vector to a priority queue can be done
+in-place, and has `O(n)` complexity. A priority queue can also be converted to
+a sorted vector in-place, allowing it to be used for an `O(n log n)` in-place
+heapsort.
+
+# Iterators
+
+## Iteration protocol
+
+The iteration protocol is defined by the `Iterator` trait in the
+`std::iter` module. The minimal implementation of the trait is a `next`
+method, yielding the next element from an iterator object:
+
+~~~
+/// An infinite stream of zeroes
+struct ZeroStream;
+
+impl Iterator<int> for ZeroStream {
+    fn next(&mut self) -> Option<int> {
+        Some(0)
+    }
+}
+~~~~
+
+Reaching the end of the iterator is signalled by returning `None` instead of
+`Some(item)`:
+
+~~~
+# fn main() {}
+/// A stream of N zeroes
+struct ZeroStream {
+    priv remaining: uint
+}
+
+impl ZeroStream {
+    fn new(n: uint) -> ZeroStream {
+        ZeroStream { remaining: n }
+    }
+}
+
+impl Iterator<int> for ZeroStream {
+    fn next(&mut self) -> Option<int> {
+        if self.remaining == 0 {
+            None
+        } else {
+            self.remaining -= 1;
+            Some(0)
+        }
+    }
+}
+~~~
+
+In general, you cannot rely on the behavior of the `next()` method after it has
+returned `None`. Some iterators may return `None` forever. Others may behave
+differently.
+
+## Container iterators
+
+Containers implement iteration over the contained elements by returning an
+iterator object. For example, vector slices several iterators available:
+
+* `iter()` and `rev_iter()`, for immutable references to the elements
+* `mut_iter()` and `mut_rev_iter()`, for mutable references to the elements
+* `move_iter()` and `move_rev_iter()`, to move the elements out by-value
+
+A typical mutable container will implement at least `iter()`, `mut_iter()` and
+`move_iter()` along with the reverse variants if it maintains an order.
+
+### Freezing
+
+Unlike most other languages with external iterators, Rust has no *iterator
+invalidation*. As long an iterator is still in scope, the compiler will prevent
+modification of the container through another handle.
+
+~~~
+let mut xs = [1, 2, 3];
+{
+    let _it = xs.iter();
+
+    // the vector is frozen for this scope, the compiler will statically
+    // prevent modification
+}
+// the vector becomes unfrozen again at the end of the scope
+~~~
+
+These semantics are due to most container iterators being implemented with `&`
+and `&mut`.
+
+## Iterator adaptors
+
+The `Iterator` trait provides many common algorithms as default methods. For
+example, the `fold` method will accumulate the items yielded by an `Iterator`
+into a single value:
+
+~~~
+let xs = [1, 9, 2, 3, 14, 12];
+let result = xs.iter().fold(0, |accumulator, item| accumulator - *item);
+assert_eq!(result, -41);
+~~~
+
+Most adaptors return an adaptor object implementing the `Iterator` trait itself:
+
+~~~
+let xs = [1, 9, 2, 3, 14, 12];
+let ys = [5, 2, 1, 8];
+let sum = xs.iter().chain(ys.iter()).fold(0, |a, b| a + *b);
+assert_eq!(sum, 57);
+~~~
+
+Some iterator adaptors may return `None` before exhausting the underlying
+iterator. Additionally, if these iterator adaptors are called again after
+returning `None`, they may call their underlying iterator again even if the
+adaptor will continue to return `None` forever. This may not be desired if the
+underlying iterator has side-effects.
+
+In order to provide a guarantee about behavior once `None` has been returned, an
+iterator adaptor named `fuse()` is provided. This returns an iterator that will
+never call its underlying iterator again once `None` has been returned:
+
+~~~
+let xs = [1,2,3,4,5];
+let mut calls = 0;
+let it = xs.iter().scan((), |_, x| {
+    calls += 1;
+    if *x < 3 { Some(x) } else { None }});
+// the iterator will only yield 1 and 2 before returning None
+// If we were to call it 5 times, calls would end up as 5, despite only 2 values
+// being yielded (and therefore 3 unique calls being made). The fuse() adaptor
+// can fix this.
+let mut it = it.fuse();
+it.next();
+it.next();
+it.next();
+it.next();
+it.next();
+assert_eq!(calls, 3);
+~~~
+
+## For loops
+
+The function `range` (or `range_inclusive`) allows to simply iterate through a given range:
+
+~~~
+for i in range(0, 5) {
+  print!("{} ", i) // prints "0 1 2 3 4"
+}
+
+for i in std::iter::range_inclusive(0, 5) { // needs explicit import
+  print!("{} ", i) // prints "0 1 2 3 4 5"
+}
+~~~
+
+The `for` keyword can be used as sugar for iterating through any iterator:
+
+~~~
+let xs = [2u, 3, 5, 7, 11, 13, 17];
+
+// print out all the elements in the vector
+for x in xs.iter() {
+    println(x.to_str())
+}
+
+// print out all but the first 3 elements in the vector
+for x in xs.iter().skip(3) {
+    println(x.to_str())
+}
+~~~
+
+For loops are *often* used with a temporary iterator object, as above. They can
+also advance the state of an iterator in a mutable location:
+
+~~~
+let xs = [1, 2, 3, 4, 5];
+let ys = ["foo", "bar", "baz", "foobar"];
+
+// create an iterator yielding tuples of elements from both vectors
+let mut it = xs.iter().zip(ys.iter());
+
+// print out the pairs of elements up to (&3, &"baz")
+for (x, y) in it {
+    println!("{} {}", *x, *y);
+
+    if *x == 3 {
+        break;
+    }
+}
+
+// yield and print the last pair from the iterator
+println!("last: {:?}", it.next());
+
+// the iterator is now fully consumed
+assert!(it.next().is_none());
+~~~
+
+## Conversion
+
+Iterators offer generic conversion to containers with the `collect` adaptor:
+
+~~~
+let xs = [0, 1, 1, 2, 3, 5, 8];
+let ys = xs.rev_iter().skip(1).map(|&x| x * 2).collect::<~[int]>();
+assert_eq!(ys, ~[10, 6, 4, 2, 2, 0]);
+~~~
+
+The method requires a type hint for the container type, if the surrounding code
+does not provide sufficient information.
+
+Containers can provide conversion from iterators through `collect` by
+implementing the `FromIterator` trait. For example, the implementation for
+vectors is as follows:
+
+~~~ {.xfail-test}
+impl<A> FromIterator<A> for ~[A] {
+    pub fn from_iterator<T: Iterator<A>>(iterator: &mut T) -> ~[A] {
+        let (lower, _) = iterator.size_hint();
+        let mut xs = with_capacity(lower);
+        for x in iterator {
+            xs.push(x);
+        }
+        xs
+    }
+}
+~~~
+
+### Size hints
+
+The `Iterator` trait provides a `size_hint` default method, returning a lower
+bound and optionally on upper bound on the length of the iterator:
+
+~~~ {.xfail-test}
+fn size_hint(&self) -> (uint, Option<uint>) { (0, None) }
+~~~
+
+The vector implementation of `FromIterator` from above uses the lower bound
+to pre-allocate enough space to hold the minimum number of elements the
+iterator will yield.
+
+The default implementation is always correct, but it should be overridden if
+the iterator can provide better information.
+
+The `ZeroStream` from earlier can provide an exact lower and upper bound:
+
+~~~
+# fn main() {}
+/// A stream of N zeroes
+struct ZeroStream {
+    priv remaining: uint
+}
+
+impl ZeroStream {
+    fn new(n: uint) -> ZeroStream {
+        ZeroStream { remaining: n }
+    }
+
+    fn size_hint(&self) -> (uint, Option<uint>) {
+        (self.remaining, Some(self.remaining))
+    }
+}
+
+impl Iterator<int> for ZeroStream {
+    fn next(&mut self) -> Option<int> {
+        if self.remaining == 0 {
+            None
+        } else {
+            self.remaining -= 1;
+            Some(0)
+        }
+    }
+}
+~~~
+
+## Double-ended iterators
+
+The `DoubleEndedIterator` trait represents an iterator able to yield elements
+from either end of a range. It inherits from the `Iterator` trait and extends
+it with the `next_back` function.
+
+A `DoubleEndedIterator` can be flipped with the `invert` adaptor, returning
+another `DoubleEndedIterator` with `next` and `next_back` exchanged.
+
+~~~
+let xs = [1, 2, 3, 4, 5, 6];
+let mut it = xs.iter();
+println!("{:?}", it.next()); // prints `Some(&1)`
+println!("{:?}", it.next()); // prints `Some(&2)`
+println!("{:?}", it.next_back()); // prints `Some(&6)`
+
+// prints `5`, `4` and `3`
+for &x in it.invert() {
+    println!("{}", x)
+}
+~~~
+
+The `rev_iter` and `mut_rev_iter` methods on vectors just return an inverted
+version of the standard immutable and mutable vector iterators.
+
+The `chain`, `map`, `filter`, `filter_map` and `inspect` adaptors are
+`DoubleEndedIterator` implementations if the underlying iterators are.
+
+~~~
+let xs = [1, 2, 3, 4];
+let ys = [5, 6, 7, 8];
+let mut it = xs.iter().chain(ys.iter()).map(|&x| x * 2);
+
+println!("{:?}", it.next()); // prints `Some(2)`
+
+// prints `16`, `14`, `12`, `10`, `8`, `6`, `4`
+for x in it.invert() {
+    println!("{}", x);
+}
+~~~
+
+The `reverse_` method is also available for any double-ended iterator yielding
+mutable references. It can be used to reverse a container in-place. Note that
+the trailing underscore is a workaround for issue #5898 and will be removed.
+
+~~~
+let mut ys = [1, 2, 3, 4, 5];
+ys.mut_iter().reverse_();
+assert_eq!(ys, [5, 4, 3, 2, 1]);
+~~~
+
+## Random-access iterators
+
+The `RandomAccessIterator` trait represents an iterator offering random access
+to the whole range. The `indexable` method retrieves the number of elements
+accessible with the `idx` method.
+
+The `chain` adaptor is an implementation of `RandomAccessIterator` if the
+underlying iterators are.
+
+~~~
+let xs = [1, 2, 3, 4, 5];
+let ys = ~[7, 9, 11];
+let mut it = xs.iter().chain(ys.iter());
+println!("{:?}", it.idx(0)); // prints `Some(&1)`
+println!("{:?}", it.idx(5)); // prints `Some(&7)`
+println!("{:?}", it.idx(7)); // prints `Some(&11)`
+println!("{:?}", it.idx(8)); // prints `None`
+
+// yield two elements from the beginning, and one from the end
+it.next();
+it.next();
+it.next_back();
+
+println!("{:?}", it.idx(0)); // prints `Some(&3)`
+println!("{:?}", it.idx(4)); // prints `Some(&9)`
+println!("{:?}", it.idx(6)); // prints `None`
+~~~
diff --git a/doc/guide-ffi.md b/doc/guide-ffi.md
new file mode 100644 (file)
index 0000000..e8eaf81
--- /dev/null
@@ -0,0 +1,430 @@
+% Rust Foreign Function Interface Guide
+
+# Introduction
+
+This guide will use the [snappy](https://code.google.com/p/snappy/)
+compression/decompression library as an introduction to writing bindings for
+foreign code. Rust is currently unable to call directly into a C++ library, but
+snappy includes a C interface (documented in
+[`snappy-c.h`](https://code.google.com/p/snappy/source/browse/trunk/snappy-c.h)).
+
+The following is a minimal example of calling a foreign function which will
+compile if snappy is installed:
+
+~~~~ {.xfail-test}
+use std::libc::size_t;
+
+#[link(name = "snappy")]
+extern {
+    fn snappy_max_compressed_length(source_length: size_t) -> size_t;
+}
+
+fn main() {
+    let x = unsafe { snappy_max_compressed_length(100) };
+    println!("max compressed length of a 100 byte buffer: {}", x);
+}
+~~~~
+
+The `extern` block is a list of function signatures in a foreign library, in
+this case with the platform's C ABI. The `#[link(...)]` attribute is used to
+instruct the linker to link against the snappy library so the symbols are
+resolved.
+
+Foreign functions are assumed to be unsafe so calls to them need to be wrapped
+with `unsafe {}` as a promise to the compiler that everything contained within
+truly is safe. C libraries often expose interfaces that aren't thread-safe, and
+almost any function that takes a pointer argument isn't valid for all possible
+inputs since the pointer could be dangling, and raw pointers fall outside of
+Rust's safe memory model.
+
+When declaring the argument types to a foreign function, the Rust compiler can
+not check if the declaration is correct, so specifying it correctly is part of
+keeping the binding correct at runtime.
+
+The `extern` block can be extended to cover the entire snappy API:
+
+~~~~ {.xfail-test}
+use std::libc::{c_int, size_t};
+
+#[link(name = "snappy")]
+extern {
+    fn snappy_compress(input: *u8,
+                       input_length: size_t,
+                       compressed: *mut u8,
+                       compressed_length: *mut size_t) -> c_int;
+    fn snappy_uncompress(compressed: *u8,
+                         compressed_length: size_t,
+                         uncompressed: *mut u8,
+                         uncompressed_length: *mut size_t) -> c_int;
+    fn snappy_max_compressed_length(source_length: size_t) -> size_t;
+    fn snappy_uncompressed_length(compressed: *u8,
+                                  compressed_length: size_t,
+                                  result: *mut size_t) -> c_int;
+    fn snappy_validate_compressed_buffer(compressed: *u8,
+                                         compressed_length: size_t) -> c_int;
+}
+~~~~
+
+# Creating a safe interface
+
+The raw C API needs to be wrapped to provide memory safety and make use of higher-level concepts
+like vectors. A library can choose to expose only the safe, high-level interface and hide the unsafe
+internal details.
+
+Wrapping the functions which expect buffers involves using the `vec::raw` module to manipulate Rust
+vectors as pointers to memory. Rust's vectors are guaranteed to be a contiguous block of memory. The
+length is number of elements currently contained, and the capacity is the total size in elements of
+the allocated memory. The length is less than or equal to the capacity.
+
+~~~~ {.xfail-test}
+pub fn validate_compressed_buffer(src: &[u8]) -> bool {
+    unsafe {
+        snappy_validate_compressed_buffer(src.as_ptr(), src.len() as size_t) == 0
+    }
+}
+~~~~
+
+The `validate_compressed_buffer` wrapper above makes use of an `unsafe` block, but it makes the
+guarantee that calling it is safe for all inputs by leaving off `unsafe` from the function
+signature.
+
+The `snappy_compress` and `snappy_uncompress` functions are more complex, since a buffer has to be
+allocated to hold the output too.
+
+The `snappy_max_compressed_length` function can be used to allocate a vector with the maximum
+required capacity to hold the compressed output. The vector can then be passed to the
+`snappy_compress` function as an output parameter. An output parameter is also passed to retrieve
+the true length after compression for setting the length.
+
+~~~~ {.xfail-test}
+pub fn compress(src: &[u8]) -> ~[u8] {
+    unsafe {
+        let srclen = src.len() as size_t;
+        let psrc = src.as_ptr();
+
+        let mut dstlen = snappy_max_compressed_length(srclen);
+        let mut dst = vec::with_capacity(dstlen as uint);
+        let pdst = dst.as_mut_ptr();
+
+        snappy_compress(psrc, srclen, pdst, &mut dstlen);
+        dst.set_len(dstlen as uint);
+        dst
+    }
+}
+~~~~
+
+Decompression is similar, because snappy stores the uncompressed size as part of the compression
+format and `snappy_uncompressed_length` will retrieve the exact buffer size required.
+
+~~~~ {.xfail-test}
+pub fn uncompress(src: &[u8]) -> Option<~[u8]> {
+    unsafe {
+        let srclen = src.len() as size_t;
+        let psrc = src.as_ptr();
+
+        let mut dstlen: size_t = 0;
+        snappy_uncompressed_length(psrc, srclen, &mut dstlen);
+
+        let mut dst = vec::with_capacity(dstlen as uint);
+        let pdst = dst.as_mut_ptr();
+
+        if snappy_uncompress(psrc, srclen, pdst, &mut dstlen) == 0 {
+            dst.set_len(dstlen as uint);
+            Some(dst)
+        } else {
+            None // SNAPPY_INVALID_INPUT
+        }
+    }
+}
+~~~~
+
+For reference, the examples used here are also available as an [library on
+GitHub](https://github.com/thestinger/rust-snappy).
+
+# Stack management
+
+Rust tasks by default run on a "large stack". This is actually implemented as a
+reserving a large segment of the address space and then lazily mapping in pages
+as they are needed. When calling an external C function, the code is invoked on
+the same stack as the rust stack. This means that there is no extra
+stack-switching mechanism in place because it is assumed that the large stack
+for the rust task is plenty for the C function to have.
+
+A planned future improvement (net yet implemented at the time of this writing)
+is to have a guard page at the end of every rust stack. No rust function will
+hit this guard page (due to Rust's usage of LLVM's `__morestack`). The intention
+for this unmapped page is to prevent infinite recursion in C from overflowing
+onto other rust stacks. If the guard page is hit, then the process will be
+terminated with a message saying that the guard page was hit.
+
+For normal external function usage, this all means that there shouldn't be any
+need for any extra effort on a user's perspective. The C stack naturally
+interleaves with the rust stack, and it's "large enough" for both to
+interoperate. If, however, it is determined that a larger stack is necessary,
+there are appropriate functions in the task spawning API to control the size of
+the stack of the task which is spawned.
+
+# Destructors
+
+Foreign libraries often hand off ownership of resources to the calling code.
+When this occurs, we must use Rust's destructors to provide safety and guarantee
+the release of these resources (especially in the case of failure).
+
+As an example, we give a reimplementation of owned boxes by wrapping `malloc`
+and `free`:
+
+~~~~
+use std::cast;
+use std::libc::{c_void, size_t, malloc, free};
+use std::ptr;
+use std::unstable::intrinsics;
+
+// Define a wrapper around the handle returned by the foreign code.
+// Unique<T> has the same semantics as ~T
+pub struct Unique<T> {
+    // It contains a single raw, mutable pointer to the object in question.
+    priv ptr: *mut T
+}
+
+// Implement methods for creating and using the values in the box.
+// NB: For simplicity and correctness, we require that T has kind Send
+// (owned boxes relax this restriction, and can contain managed (GC) boxes).
+// This is because, as implemented, the garbage collector would not know
+// about any shared boxes stored in the malloc'd region of memory.
+impl<T: Send> Unique<T> {
+    pub fn new(value: T) -> Unique<T> {
+        unsafe {
+            let ptr = malloc(std::mem::size_of::<T>() as size_t) as *mut T;
+            assert!(!ptr::is_null(ptr));
+            // `*ptr` is uninitialized, and `*ptr = value` would attempt to destroy it
+            // move_val_init moves a value into this memory without
+            // attempting to drop the original value.
+            intrinsics::move_val_init(&mut *ptr, value);
+            Unique{ptr: ptr}
+        }
+    }
+
+    // the 'r lifetime results in the same semantics as `&*x` with ~T
+    pub fn borrow<'r>(&'r self) -> &'r T {
+        unsafe { cast::copy_lifetime(self, &*self.ptr) }
+    }
+
+    // the 'r lifetime results in the same semantics as `&mut *x` with ~T
+    pub fn borrow_mut<'r>(&'r mut self) -> &'r mut T {
+        unsafe { cast::copy_mut_lifetime(self, &mut *self.ptr) }
+    }
+}
+
+// The key ingredient for safety, we associate a destructor with
+// Unique<T>, making the struct manage the raw pointer: when the
+// struct goes out of scope, it will automatically free the raw pointer.
+// NB: This is an unsafe destructor, because rustc will not normally
+// allow destructors to be associated with parametrized types, due to
+// bad interaction with managed boxes. (With the Send restriction,
+// we don't have this problem.)
+#[unsafe_destructor]
+impl<T: Send> Drop for Unique<T> {
+    fn drop(&mut self) {
+        unsafe {
+            let x = intrinsics::uninit(); // dummy value to swap in
+            // We need to move the object out of the box, so that
+            // the destructor is called (at the end of this scope.)
+            ptr::replace_ptr(self.ptr, x);
+            free(self.ptr as *c_void)
+        }
+    }
+}
+
+// A comparison between the built-in ~ and this reimplementation
+fn main() {
+    {
+        let mut x = ~5;
+        *x = 10;
+    } // `x` is freed here
+
+    {
+        let mut y = Unique::new(5);
+        *y.borrow_mut() = 10;
+    } // `y` is freed here
+}
+~~~~
+
+# Linking
+
+The `link` attribute on `extern` blocks provides the basic building block for
+instructing rustc how it will link to native libraries. There are two accepted
+forms of the link attribute today:
+
+* `#[link(name = "foo")]`
+* `#[link(name = "foo", kind = "bar")]`
+
+In both of these cases, `foo` is the name of the native library that we're
+linking to, and in the second case `bar` is the type of native library that the
+compiler is linking to. There are currently three known types of native
+libraries:
+
+* Dynamic - `#[link(name = "readline")]
+* Static - `#[link(name = "my_build_dependency", kind = "static")]
+* Frameworks - `#[link(name = "CoreFoundation", kind = "framework")]
+
+Note that frameworks are only available on OSX targets.
+
+The different `kind` values are meant to differentiate how the native library
+participates in linkage. From a linkage perspective, the rust compiler creates
+two flavors of artifacts: partial (rlib/staticlib) and final (dylib/binary).
+Native dynamic libraries and frameworks are propagated to the final artifact
+boundary, while static libraries are not propagated at all.
+
+A few examples of how this model can be used are:
+
+* A native build dependency. Sometimes some C/C++ glue is needed when writing
+  some rust code, but distribution of the C/C++ code in a library format is just
+  a burden. In this case, the code will be archived into `libfoo.a` and then the
+  rust crate would declare a dependency via `#[link(name = "foo", kind =
+  "static")]`.
+
+  Regardless of the flavor of output for the crate, the native static library
+  will be included in the output, meaning that distribution of the native static
+  library is not necessary.
+
+* A normal dynamic dependency. Common system libraries (like `readline`) are
+  available on a large number of systems, and often a static copy of these
+  libraries cannot be found. When this dependency is included in a rust crate,
+  partial targets (like rlibs) will not link to the library, but when the rlib
+  is included in a final target (like a binary), the native library will be
+  linked in.
+
+On OSX, frameworks behave with the same semantics as a dynamic library.
+
+## The `link_args` attribute
+
+There is one other way to tell rustc how to customize linking, and that is via
+the `link_args` attribute. This attribute is applied to `extern` blocks and
+specifies raw flags which need to get passed to the linker when producing an
+artifact. An example usage would be:
+
+~~~ {.xfail-test}
+#[link_args = "-foo -bar -baz"]
+extern {}
+~~~
+
+Note that this feature is currently hidden behind the `feature(link_args)` gate
+because this is not a sanctioned way of performing linking. Right now rustc
+shells out to the system linker, so it makes sense to provide extra command line
+arguments, but this will not always be the case. In the future rustc may use
+LLVM directly to link native libraries in which case `link_args` will have no
+meaning.
+
+It is highly recommended to *not* use this attribute, and rather use the more
+formal `#[link(...)]` attribute on `extern` blocks instead.
+
+# Unsafe blocks
+
+Some operations, like dereferencing unsafe pointers or calling functions that have been marked
+unsafe are only allowed inside unsafe blocks. Unsafe blocks isolate unsafety and are a promise to
+the compiler that the unsafety does not leak out of the block.
+
+Unsafe functions, on the other hand, advertise it to the world. An unsafe function is written like
+this:
+
+~~~~
+unsafe fn kaboom(ptr: *int) -> int { *ptr }
+~~~~
+
+This function can only be called from an `unsafe` block or another `unsafe` function.
+
+# Accessing foreign globals
+
+Foreign APIs often export a global variable which could do something like track
+global state. In order to access these variables, you declare them in `extern`
+blocks with the `static` keyword:
+
+~~~{.xfail-test}
+use std::libc;
+
+#[link(name = "readline")]
+extern {
+    static rl_readline_version: libc::c_int;
+}
+
+fn main() {
+    println!("You have readline version {} installed.",
+             rl_readline_version as int);
+}
+~~~
+
+Alternatively, you may need to alter global state provided by a foreign
+interface. To do this, statics can be declared with `mut` so rust can mutate
+them.
+
+~~~{.xfail-test}
+use std::libc;
+use std::ptr;
+
+#[link(name = "readline")]
+extern {
+    static mut rl_prompt: *libc::c_char;
+}
+
+fn main() {
+    do "[my-awesome-shell] $".as_c_str |buf| {
+        unsafe { rl_prompt = buf; }
+        // get a line, process it
+        unsafe { rl_prompt = ptr::null(); }
+    }
+}
+~~~
+
+# Foreign calling conventions
+
+Most foreign code exposes a C ABI, and Rust uses the platform's C calling convention by default when
+calling foreign functions. Some foreign functions, most notably the Windows API, use other calling
+conventions. Rust provides a way to tell the compiler which convention to use:
+
+~~~~
+#[cfg(target_os = "win32", target_arch = "x86")]
+#[link_name = "kernel32"]
+extern "stdcall" {
+    fn SetEnvironmentVariableA(n: *u8, v: *u8) -> std::libc::c_int;
+}
+~~~~
+
+This applies to the entire `extern` block. The list of supported ABI constraints
+are:
+
+* `stdcall`
+* `aapcs`
+* `cdecl`
+* `fastcall`
+* `Rust`
+* `rust-intrinsic`
+* `system`
+* `C`
+
+Most of the abis in this list are self-explanatory, but the `system` abi may
+seem a little odd. This constraint selects whatever the appropriate ABI is for
+interoperating with the target's libraries. For example, on win32 with a x86
+architecture, this means that the abi used would be `stdcall`. On x86_64,
+however, windows uses the `C` calling convention, so `C` would be used. This
+means that in our previous example, we could have used `extern "system" { ... }`
+to define a block for all windows systems, not just x86 ones.
+
+# Interoperability with foreign code
+
+Rust guarantees that the layout of a `struct` is compatible with the platform's representation in C.
+A `#[packed]` attribute is available, which will lay out the struct members without padding.
+However, there are currently no guarantees about the layout of an `enum`.
+
+Rust's owned and managed boxes use non-nullable pointers as handles which point to the contained
+object. However, they should not be manually created because they are managed by internal
+allocators. Borrowed pointers can safely be assumed to be non-nullable pointers directly to the
+type. However, breaking the borrow checking or mutability rules is not guaranteed to be safe, so
+prefer using raw pointers (`*`) if that's needed because the compiler can't make as many assumptions
+about them.
+
+Vectors and strings share the same basic memory layout, and utilities are available in the `vec` and
+`str` modules for working with C APIs. However, strings are not terminated with `\0`. If you need a
+NUL-terminated string for interoperability with C, you should use the `c_str::to_c_str` function.
+
+The standard library includes type aliases and function definitions for the C standard library in
+the `libc` module, and Rust links against `libc` and `libm` by default.
diff --git a/doc/guide-macros.md b/doc/guide-macros.md
new file mode 100644 (file)
index 0000000..f4917fd
--- /dev/null
@@ -0,0 +1,407 @@
+% Rust Macros Guide
+
+# Introduction
+
+Functions are the primary tool that programmers can use to build abstractions.
+Sometimes, however, programmers want to abstract over compile-time syntax
+rather than run-time values.
+Macros provide syntactic abstraction.
+For an example of how this can be useful, consider the following two code fragments,
+which both pattern-match on their input and both return early in one case,
+doing nothing otherwise:
+
+~~~~
+# enum t { special_a(uint), special_b(uint) };
+# fn f() -> uint {
+# let input_1 = special_a(0);
+# let input_2 = special_a(0);
+match input_1 {
+    special_a(x) => { return x; }
+    _ => {}
+}
+// ...
+match input_2 {
+    special_b(x) => { return x; }
+    _ => {}
+}
+# return 0u;
+# }
+~~~~
+
+This code could become tiresome if repeated many times.
+However, no function can capture its functionality to make it possible
+to abstract the repetition away.
+Rust's macro system, however, can eliminate the repetition. Macros are
+lightweight custom syntax extensions, themselves defined using the
+`macro_rules!` syntax extension. The following `early_return` macro captures
+the pattern in the above code:
+
+~~~~
+# enum t { special_a(uint), special_b(uint) };
+# fn f() -> uint {
+# let input_1 = special_a(0);
+# let input_2 = special_a(0);
+macro_rules! early_return(
+    ($inp:expr $sp:ident) => ( // invoke it like `(input_5 special_e)`
+        match $inp {
+            $sp(x) => { return x; }
+            _ => {}
+        }
+    );
+)
+// ...
+early_return!(input_1 special_a);
+// ...
+early_return!(input_2 special_b);
+# return 0;
+# }
+~~~~
+
+Macros are defined in pattern-matching style: in the above example, the text
+`($inp:expr $sp:ident)` that appears on the left-hand side of the `=>` is the
+*macro invocation syntax*, a pattern denoting how to write a call to the
+macro. The text on the right-hand side of the `=>`, beginning with `match
+$inp`, is the *macro transcription syntax*: what the macro expands to.
+
+# Invocation syntax
+
+The macro invocation syntax specifies the syntax for the arguments to the
+macro. It appears on the left-hand side of the `=>` in a macro definition. It
+conforms to the following rules:
+
+1. It must be surrounded by parentheses.
+2. `$` has special meaning (described below).
+3. The `()`s, `[]`s, and `{}`s it contains must balance. For example, `([)` is
+forbidden.
+
+Otherwise, the invocation syntax is free-form.
+
+To take as an argument a fragment of Rust code, write `$` followed by a name
+ (for use on the right-hand side), followed by a `:`, followed by a *fragment
+ specifier*. The fragment specifier denotes the sort of fragment to match. The
+ most common fragment specifiers are:
+
+* `ident` (an identifier, referring to a variable or item. Examples: `f`, `x`,
+  `foo`.)
+* `expr` (an expression. Examples: `2 + 2`; `if true then { 1 } else { 2 }`;
+  `f(42)`.)
+* `ty` (a type. Examples: `int`, `~[(char, ~str)]`, `&T`.)
+* `pat` (a pattern, usually appearing in a `match` or on the left-hand side of
+  a declaration. Examples: `Some(t)`; `(17, 'a')`; `_`.)
+* `block` (a sequence of actions. Example: `{ log(error, "hi"); return 12; }`)
+
+The parser interprets any token that's not preceded by a `$` literally. Rust's usual
+rules of tokenization apply,
+
+So `($x:ident -> (($e:expr)))`, though excessively fancy, would designate a macro
+that could be invoked like: `my_macro!(i->(( 2+2 )))`.
+
+## Invocation location
+
+A macro invocation may take the place of (and therefore expand to)
+an expression, an item, or a statement.
+The Rust parser will parse the macro invocation as a "placeholder"
+for whichever of those three nonterminals is appropriate for the location.
+
+At expansion time, the output of the macro will be parsed as whichever of the
+three nonterminals it stands in for. This means that a single macro might,
+for example, expand to an item or an expression, depending on its arguments
+(and cause a syntax error if it is called with the wrong argument for its
+location). Although this behavior sounds excessively dynamic, it is known to
+be useful under some circumstances.
+
+
+# Transcription syntax
+
+The right-hand side of the `=>` follows the same rules as the left-hand side,
+except that a `$` need only be followed by the name of the syntactic fragment
+to transcribe into the macro expansion; its type need not be repeated.
+
+The right-hand side must be enclosed by delimiters, which the transcriber ignores.
+Therefore `() => ((1,2,3))` is a macro that expands to a tuple expression,
+`() => (let $x=$val)` is a macro that expands to a statement,
+and `() => (1,2,3)` is a macro that expands to a syntax error
+(since the transcriber interprets the parentheses on the right-hand-size as delimiters,
+and `1,2,3` is not a valid Rust expression on its own).
+
+Except for permissibility of `$name` (and `$(...)*`, discussed below), the
+right-hand side of a macro definition is ordinary Rust syntax. In particular,
+macro invocations (including invocations of the macro currently being defined)
+are permitted in expression, statement, and item locations. However, nothing
+else about the code is examined or executed by the macro system; execution
+still has to wait until run-time.
+
+## Interpolation location
+
+The interpolation `$argument_name` may appear in any location consistent with
+its fragment specifier (i.e., if it is specified as `ident`, it may be used
+anywhere an identifier is permitted).
+
+# Multiplicity
+
+## Invocation
+
+Going back to the motivating example, recall that `early_return` expanded into
+a `match` that would `return` if the `match`'s scrutinee matched the
+"special case" identifier provided as the second argument to `early_return`,
+and do nothing otherwise. Now suppose that we wanted to write a
+version of `early_return` that could handle a variable number of "special"
+cases.
+
+The syntax `$(...)*` on the left-hand side of the `=>` in a macro definition
+accepts zero or more occurrences of its contents. It works much
+like the `*` operator in regular expressions. It also supports a
+separator token (a comma-separated list could be written `$(...),*`), and `+`
+instead of `*` to mean "at least one".
+
+~~~~
+# enum t { special_a(uint),special_b(uint),special_c(uint),special_d(uint)};
+# fn f() -> uint {
+# let input_1 = special_a(0);
+# let input_2 = special_a(0);
+macro_rules! early_return(
+    ($inp:expr, [ $($sp:ident)|+ ]) => (
+        match $inp {
+            $(
+                $sp(x) => { return x; }
+            )+
+            _ => {}
+        }
+    );
+)
+// ...
+early_return!(input_1, [special_a|special_c|special_d]);
+// ...
+early_return!(input_2, [special_b]);
+# return 0;
+# }
+~~~~
+
+### Transcription
+
+As the above example demonstrates, `$(...)*` is also valid on the right-hand
+side of a macro definition. The behavior of `*` in transcription,
+especially in cases where multiple `*`s are nested, and multiple different
+names are involved, can seem somewhat magical and intuitive at first. The
+system that interprets them is called "Macro By Example". The two rules to
+keep in mind are (1) the behavior of `$(...)*` is to walk through one "layer"
+of repetitions for all of the `$name`s it contains in lockstep, and (2) each
+`$name` must be under at least as many `$(...)*`s as it was matched against.
+If it is under more, it'll be repeated, as appropriate.
+
+## Parsing limitations
+
+
+For technical reasons, there are two limitations to the treatment of syntax
+fragments by the macro parser:
+
+1. The parser will always parse as much as possible of a Rust syntactic
+fragment. For example, if the comma were omitted from the syntax of
+`early_return!` above, `input_1 [` would've been interpreted as the beginning
+of an array index. In fact, invoking the macro would have been impossible.
+2. The parser must have eliminated all ambiguity by the time it reaches a
+`$name:fragment_specifier` declaration. This limitation can result in parse
+errors when declarations occur at the beginning of, or immediately after,
+a `$(...)*`. For example, the grammar `$($t:ty)* $e:expr` will always fail to
+parse because the parser would be forced to choose between parsing `t` and
+parsing `e`. Changing the invocation syntax to require a distinctive token in
+front can solve the problem. In the above example, `$(T $t:ty)* E $e:exp`
+solves the problem.
+
+# Macro argument pattern matching
+
+## Motivation
+
+Now consider code like the following:
+
+~~~~
+# enum t1 { good_1(t2, uint), bad_1 };
+# struct t2 { body: t3 }
+# enum t3 { good_2(uint), bad_2};
+# fn f(x: t1) -> uint {
+match x {
+    good_1(g1, val) => {
+        match g1.body {
+            good_2(result) => {
+                // complicated stuff goes here
+                return result + val;
+            },
+            _ => fail!("Didn't get good_2")
+        }
+    }
+    _ => return 0 // default value
+}
+# }
+~~~~
+
+All the complicated stuff is deeply indented, and the error-handling code is
+separated from matches that fail. We'd like to write a macro that performs
+a match, but with a syntax that suits the problem better. The following macro
+can solve the problem:
+
+~~~~
+macro_rules! biased_match (
+    // special case: `let (x) = ...` is illegal, so use `let x = ...` instead
+    ( ($e:expr) ~ ($p:pat) else $err:stmt ;
+      binds $bind_res:ident
+    ) => (
+        let $bind_res = match $e {
+            $p => ( $bind_res ),
+            _ => { $err }
+        };
+    );
+    // more than one name; use a tuple
+    ( ($e:expr) ~ ($p:pat) else $err:stmt ;
+      binds $( $bind_res:ident ),*
+    ) => (
+        let ( $( $bind_res ),* ) = match $e {
+            $p => ( $( $bind_res ),* ),
+            _ => { $err }
+        };
+    )
+)
+
+# enum t1 { good_1(t2, uint), bad_1 };
+# struct t2 { body: t3 }
+# enum t3 { good_2(uint), bad_2};
+# fn f(x: t1) -> uint {
+biased_match!((x)       ~ (good_1(g1, val)) else { return 0 };
+              binds g1, val )
+biased_match!((g1.body) ~ (good_2(result) )
+                  else { fail!("Didn't get good_2") };
+              binds result )
+// complicated stuff goes here
+return result + val;
+# }
+~~~~
+
+This solves the indentation problem. But if we have a lot of chained matches
+like this, we might prefer to write a single macro invocation. The input
+pattern we want is clear:
+~~~~
+# macro_rules! b(
+    ( $( ($e:expr) ~ ($p:pat) else $err:stmt ; )*
+      binds $( $bind_res:ident ),*
+    )
+# => (0))
+~~~~
+
+However, it's not possible to directly expand to nested match statements. But
+there is a solution.
+
+## The recursive approach to macro writing
+
+A macro may accept multiple different input grammars. The first one to
+successfully match the actual argument to a macro invocation is the one that
+"wins".
+
+In the case of the example above, we want to write a recursive macro to
+process the semicolon-terminated lines, one-by-one. So, we want the following
+input patterns:
+
+~~~~
+# macro_rules! b(
+    ( binds $( $bind_res:ident ),* )
+# => (0))
+~~~~
+...and:
+
+~~~~
+# macro_rules! b(
+    (    ($e     :expr) ~ ($p     :pat) else $err     :stmt ;
+      $( ($e_rest:expr) ~ ($p_rest:pat) else $err_rest:stmt ; )*
+      binds  $( $bind_res:ident ),*
+    )
+# => (0))
+~~~~
+
+The resulting macro looks like this. Note that the separation into
+`biased_match!` and `biased_match_rec!` occurs only because we have an outer
+piece of syntax (the `let`) which we only want to transcribe once.
+
+~~~~
+
+macro_rules! biased_match_rec (
+    // Handle the first layer
+    (   ($e     :expr) ~ ($p     :pat) else $err     :stmt ;
+     $( ($e_rest:expr) ~ ($p_rest:pat) else $err_rest:stmt ; )*
+     binds $( $bind_res:ident ),*
+    ) => (
+        match $e {
+            $p => {
+                // Recursively handle the next layer
+                biased_match_rec!($( ($e_rest) ~ ($p_rest) else $err_rest ; )*
+                                  binds $( $bind_res ),*
+                )
+            }
+            _ => { $err }
+        }
+    );
+    ( binds $( $bind_res:ident ),* ) => ( ($( $bind_res ),*) )
+)
+
+// Wrap the whole thing in a `let`.
+macro_rules! biased_match (
+    // special case: `let (x) = ...` is illegal, so use `let x = ...` instead
+    ( $( ($e:expr) ~ ($p:pat) else $err:stmt ; )*
+      binds $bind_res:ident
+    ) => (
+        let ( $( $bind_res ),* ) = biased_match_rec!(
+            $( ($e) ~ ($p) else $err ; )*
+            binds $bind_res
+        );
+    );
+    // more than one name: use a tuple
+    ( $( ($e:expr) ~ ($p:pat) else $err:stmt ; )*
+      binds  $( $bind_res:ident ),*
+    ) => (
+        let ( $( $bind_res ),* ) = biased_match_rec!(
+            $( ($e) ~ ($p) else $err ; )*
+            binds $( $bind_res ),*
+        );
+    )
+)
+
+
+# enum t1 { good_1(t2, uint), bad_1 };
+# struct t2 { body: t3 }
+# enum t3 { good_2(uint), bad_2};
+# fn f(x: t1) -> uint {
+biased_match!(
+    (x)       ~ (good_1(g1, val)) else { return 0 };
+    (g1.body) ~ (good_2(result) ) else { fail!("Didn't get good_2") };
+    binds val, result )
+// complicated stuff goes here
+return result + val;
+# }
+~~~~
+
+This technique applies to many cases where transcribing a result all at once is not possible.
+The resulting code resembles ordinary functional programming in some respects,
+but has some important differences from functional programming.
+
+The first difference is important, but also easy to forget: the transcription
+(right-hand) side of a `macro_rules!` rule is literal syntax, which can only
+be executed at run-time. If a piece of transcription syntax does not itself
+appear inside another macro invocation, it will become part of the final
+program. If it is inside a macro invocation (for example, the recursive
+invocation of `biased_match_rec!`), it does have the opportunity to affect
+transcription, but only through the process of attempted pattern matching.
+
+The second, related, difference is that the evaluation order of macros feels
+"backwards" compared to ordinary programming. Given an invocation
+`m1!(m2!())`, the expander first expands `m1!`, giving it as input the literal
+syntax `m2!()`. If it transcribes its argument unchanged into an appropriate
+position (in particular, not as an argument to yet another macro invocation),
+the expander will then proceed to evaluate `m2!()` (along with any other macro
+invocations `m1!(m2!())` produced).
+
+# A final note
+
+Macros, as currently implemented, are not for the faint of heart. Even
+ordinary syntax errors can be more difficult to debug when they occur inside a
+macro, and errors caused by parse problems in generated code can be very
+tricky. Invoking the `log_syntax!` macro can help elucidate intermediate
+states, invoking `trace_macros!(true)` will automatically print those
+intermediate states out, and passing the flag `--pretty expanded` as a
+command-line argument to the compiler will show the result of expansion.
diff --git a/doc/guide-rustpkg.md b/doc/guide-rustpkg.md
new file mode 100644 (file)
index 0000000..149f89e
--- /dev/null
@@ -0,0 +1,270 @@
+% Rust Packaging Guide
+
+# Introduction
+
+Sharing is caring. Rust comes with a tool, `rustpkg`, which allows you to
+package up your Rust code and share it with other people. This guide will
+get you started on all of the concepts and commands you need to give the gift
+of Rust code to someone else.
+
+# Installing External Packages
+
+First, let's try to use an external package somehow. I've made a sample package
+called `hello` to demonstrate how to do so.  Here's how `hello` is used:
+
+~~~~
+extern mod hello;
+
+fn main() {
+    hello::world();
+}
+~~~~
+
+Easy! But if you try to compile this, you'll get an error:
+
+~~~~ {.notrust}
+$ rustc main.rs 
+main.rs:1:0: 1:17 error: can't find crate for `hello`
+main.rs:1 extern mod hello;
+          ^~~~~~~~~~~~~~~~~
+~~~~
+
+This makes sense, as we haven't gotten it from anywhere yet!  Luckily for us,
+`rustpkg` has an easy way to fetch others' code: the `install` command. It's
+used like this:
+
+~~~ {.notrust}
+$ rustpkg install PKG_ID
+~~~
+
+This will install a package named `PKG_ID` into your current Rust environment.
+I called it `PKG_ID` in this example because `rustpkg` calls this a 'package
+identifier.' When using it with an external package like this, it's often a
+URI fragment.  You see, Rust has no central authority for packages. You can
+build your own `hello` library if you want, and that's fine. We'd both host
+them in different places and different projects would rely on whichever version
+they preferred.
+
+To install the `hello` library, simply run this in your terminal:
+
+~~~ {.notrust}
+$ rustpkg install github.com/steveklabnik/hello
+~~~
+
+You should see a message that looks like this:
+
+~~~ {.notrust}
+note: Installed package github.com/steveklabnik/hello-0.1 to /some/path/.rust
+~~~
+
+Now, compiling our example should work:
+
+~~~ {.notrust}
+$ rustc main.rs
+$ ./main 
+Hello, world.
+~~~
+
+Simple! That's all it takes.
+
+# Workspaces
+
+Before we can talk about how to make packages of your own, you have to
+understand the big concept with `rustpkg`: workspaces. A 'workspace' is simply
+a directory that has certain sub-directories that `rustpkg` expects. Different
+Rust projects will go into different workspaces.
+
+A workspace consists of any directory that has the following
+directories:
+
+* `src`: The directory where all the source code goes.
+* `build`: This directory contains all of the build output.
+* `lib`: The directory where any libraries distributed with the package go.
+* `bin`: This directory holds any binaries distributed with the package.
+
+There are also default file names you'll want to follow as well:
+
+* `main.rs`: A file that's going to become an executable.
+* `lib.rs`: A file that's going to become a library.
+
+# Building your own Package
+
+Now that you've got workspaces down, let's build your own copy of `hello`. Go
+to wherever you keep your personal projects, and let's make all of the
+directories we'll need. I'll refer to this personal project directory as
+`~/src` for the rest of this guide.
+
+## Creating our workspace
+
+~~~ {.notrust}
+$ cd ~/src
+$ mkdir -p hello/src/hello
+$ cd hello
+~~~
+
+Easy enough! Let's do one or two more things that are nice to do:
+
+~~~ {.notrust}
+$ git init .
+$ cat > README.md
+# hello
+
+A simple package for Rust.
+
+## Installation
+
+```
+$ rustpkg install github.com/YOUR_USERNAME/hello
+```
+^D
+$ cat > .gitignore
+.rust
+build
+^D
+$ git commit -am "Initial commit."
+~~~
+
+If you're not familliar with the `cat >` idiom, it will make files with the
+text you type inside. Control-D (`^D`) ends the text for the file.
+
+Anyway, we've got a README and a `.gitignore`. Let's talk about that
+`.gitignore` for a minute: we are ignoring two directories, `build` and
+`.rust`. `build`, as we discussed earlier, is for build artifacts, and we don't
+want to check those into a repository. `.rust` is a directory that `rustpkg`
+uses to keep track of its own settings, as well as the source code of any other
+external packages that this workspace uses. This is where that `rustpkg
+install` puts all of its files. Those are also not to go into our repository,
+so we ignore it all as well.
+
+Next, let's add a source file:
+
+~~~
+#[desc = "A hello world Rust package."];
+#[license = "MIT"];
+
+pub fn world() {
+    println("Hello, world.");
+}
+~~~
+
+Put this into `src/hello/lib.rs`. Let's talk about each of these attributes:
+
+## Crate attributes for packages
+
+`license` is equally simple: the license we want this code to have. I chose MIT
+here, but you should pick whatever license makes the most sense for you.
+
+`desc` is a description of the package and what it does. This should just be a
+sentence or two.
+
+## Building your package
+
+Building your package is simple:
+
+~~~ {.notrust}
+$ rustpkg build hello
+~~~
+
+This will compile `src/hello/lib.rs` into a library. After this process
+completes, you'll want to check out `build`:
+
+~~~ {.notrust}
+$ ls build/x86_64-unknown-linux-gnu/hello/
+libhello-ed8619dad9ce7d58-0.1.0.so
+~~~
+
+This directory naming structure is called a 'build triple,' and is because I'm
+on 64 bit Linux. Yours may differ based on platform.
+
+You'll also notice that `src/hello/lib.rs` turned into
+`libhello-ed8619dad9ce7d58-0.1.0.so`. This is a simple combination of the
+library name, a hash of its content, and the version.
+
+Now that your library builds, you'll want to commit:
+
+~~~ {.notrust}
+$ git add src
+$ git commit -m "Adding source code."
+~~~
+
+If you're using GitHub, after creating the project, do this:
+
+~~~ {.notrust}
+$ git remote add origin git@github.com:YOUR_USERNAME/hello.git
+$ git push origin -u master
+~~~
+
+Now you can install and use it! Go anywhere else in your filesystem:
+
+~~~ {.notrust}
+$ cd ~/src/foo
+$ rustpkg install github.com/YOUR_USERNAME/hello
+WARNING: The Rust package manager is experimental and may be unstable
+note: Installed package github.com/YOUR_USERNAME/hello-0.1 to /home/yourusername/src/hello/.rust
+~~~
+
+That's it!
+
+# Testing your Package
+
+Testing your package is simple as well. First, let's change `src/hello/lib.rs` to contain
+a function that can be sensibly tested:
+
+~~~
+#[desc = "A Rust package for determining whether unsigned integers are even."];
+#[license = "MIT"];
+
+pub fn is_even(i: uint) -> bool {
+    i % 2 == 0
+}
+~~~
+
+Once you've edited `lib.rs`, you can create a second crate file, `src/hello/test.rs`,
+to put tests in:
+
+~~~
+#[license = "MIT"];
+extern mod hello;
+use hello::is_even;
+
+#[test]
+fn test_is_even() {
+    assert!(is_even(0));
+    assert!(!is_even(1));
+    assert!(is_even(2));
+}
+~~~
+
+Note that you have to import the crate you just created in `lib.rs` with the
+`extern mod hello` directive. That's because you're putting the tests in a different
+crate from the main library that you created.
+
+Now, you can use the `rustpkg test` command to build this test crate (and anything else
+it depends on) and run the tests, all in one step:
+
+~~~ {.notrust}
+$ rustpkg test hello
+WARNING: The Rust package manager is experimental and may be unstable
+note: Installed package hello-0.1 to /Users/tjc/.rust
+
+running 1 test
+test test_is_even ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
+~~~
+
+# More resources
+
+There's a lot more going on with `rustpkg`, this is just to get you started.
+Check out [the rustpkg manual](rustpkg.html) for the full details on how to
+customize `rustpkg`.
+
+A tag was created on GitHub specifically for `rustpkg`-related issues. You can
+[see all the Issues for rustpkg
+here](https://github.com/mozilla/rust/issues?direction=desc&labels=A-pkg&sort=created&state=open),
+with bugs as well as new feature plans. `rustpkg` is still under development,
+and so may be a bit flaky at the moment.
+
+You may also want to check out [this blog
+post](http://tim.dreamwidth.org/1820526.html), which contains some of the early
+design decisions and justifications.
diff --git a/doc/guide-tasks.md b/doc/guide-tasks.md
new file mode 100644 (file)
index 0000000..45977e4
--- /dev/null
@@ -0,0 +1,515 @@
+% Rust Tasks and Communication Guide
+
+# Introduction
+
+Rust provides safe concurrency through a combination
+of lightweight, memory-isolated tasks and message passing.
+This guide will describe the concurrency model in Rust, how it
+relates to the Rust type system, and introduce
+the fundamental library abstractions for constructing concurrent programs.
+
+Rust tasks are not the same as traditional threads: rather,
+they are considered _green threads_, lightweight units of execution that the Rust
+runtime schedules cooperatively onto a small number of operating system threads.
+On a multi-core system Rust tasks will be scheduled in parallel by default.
+Because tasks are significantly
+cheaper to create than traditional threads, Rust can create hundreds of
+thousands of concurrent tasks on a typical 32-bit system.
+In general, all Rust code executes inside a task, including the `main` function.
+
+In order to make efficient use of memory Rust tasks have dynamically sized stacks.
+A task begins its life with a small
+amount of stack space (currently in the low thousands of bytes, depending on
+platform), and acquires more stack as needed.
+Unlike in languages such as C, a Rust task cannot accidentally write to
+memory beyond the end of the stack, causing crashes or worse.
+
+Tasks provide failure isolation and recovery. When a fatal error occurs in Rust
+code as a result of an explicit call to `fail!()`, an assertion failure, or
+another invalid operation, the runtime system destroys the entire
+task. Unlike in languages such as Java and C++, there is no way to `catch` an
+exception. Instead, tasks may monitor each other for failure.
+
+Tasks use Rust's type system to provide strong memory safety guarantees. In
+particular, the type system guarantees that tasks cannot share mutable state
+with each other. Tasks communicate with each other by transferring _owned_
+data through the global _exchange heap_.
+
+## A note about the libraries
+
+While Rust's type system provides the building blocks needed for safe
+and efficient tasks, all of the task functionality itself is implemented
+in the standard and extra libraries, which are still under development
+and do not always present a consistent or complete interface.
+
+For your reference, these are the standard modules involved in Rust
+concurrency at this writing:
+
+* [`std::task`] - All code relating to tasks and task scheduling,
+* [`std::comm`] - The message passing interface,
+* [`extra::comm`] - Additional messaging types based on `std::comm`,
+* [`extra::sync`] - More exotic synchronization tools, including locks,
+* [`extra::arc`] - The Arc (atomically reference counted) type,
+  for safely sharing immutable data,
+* [`extra::future`] - A type representing values that may be computed concurrently and retrieved at a later time.
+
+[`std::task`]: std/task/index.html
+[`std::comm`]: std/comm/index.html
+[`extra::comm`]: extra/comm/index.html
+[`extra::sync`]: extra/sync/index.html
+[`extra::arc`]: extra/arc/index.html
+[`extra::future`]: extra/future/index.html
+
+# Basics
+
+The programming interface for creating and managing tasks lives
+in the `task` module of the `std` library, and is thus available to all
+Rust code by default. At its simplest, creating a task is a matter of
+calling the `spawn` function with a closure argument. `spawn` executes the
+closure in the new task.
+
+~~~~
+# use std::task::spawn;
+
+// Print something profound in a different task using a named function
+fn print_message() { println("I am running in a different task!"); }
+spawn(print_message);
+
+// Print something more profound in a different task using a lambda expression
+spawn(proc() println("I am also running in a different task!") );
+
+// The canonical way to spawn is using `do` notation
+do spawn {
+    println("I too am running in a different task!");
+}
+~~~~
+
+In Rust, there is nothing special about creating tasks: a task is not a
+concept that appears in the language semantics. Instead, Rust's type system
+provides all the tools necessary to implement safe concurrency: particularly,
+_owned types_. The language leaves the implementation details to the standard
+library.
+
+The `spawn` function has a very simple type signature: `fn spawn(f:
+proc())`. Because it accepts only owned closures, and owned closures
+contain only owned data, `spawn` can safely move the entire closure
+and all its associated state into an entirely different task for
+execution. Like any closure, the function passed to `spawn` may capture
+an environment that it carries across tasks.
+
+~~~
+# use std::task::spawn;
+# fn generate_task_number() -> int { 0 }
+// Generate some state locally
+let child_task_number = generate_task_number();
+
+do spawn {
+    // Capture it in the remote task
+    println!("I am child number {}", child_task_number);
+}
+~~~
+
+## Communication
+
+Now that we have spawned a new task, it would be nice if we could
+communicate with it. Recall that Rust does not have shared mutable
+state, so one task may not manipulate variables owned by another task.
+Instead we use *pipes*.
+
+A pipe is simply a pair of endpoints: one for sending messages and another for
+receiving messages. Pipes are low-level communication building-blocks and so
+come in a variety of forms, each one appropriate for a different use case. In
+what follows, we cover the most commonly used varieties.
+
+The simplest way to create a pipe is to use `Chan::new`
+function to create a `(Port, Chan)` pair. In Rust parlance, a *channel*
+is a sending endpoint of a pipe, and a *port* is the receiving
+endpoint. Consider the following example of calculating two results
+concurrently:
+
+~~~~
+# use std::task::spawn;
+
+let (port, chan): (Port<int>, Chan<int>) = Chan::new();
+
+do spawn || {
+    let result = some_expensive_computation();
+    chan.send(result);
+}
+
+some_other_expensive_computation();
+let result = port.recv();
+# fn some_expensive_computation() -> int { 42 }
+# fn some_other_expensive_computation() {}
+~~~~
+
+Let's examine this example in detail. First, the `let` statement creates a
+stream for sending and receiving integers (the left-hand side of the `let`,
+`(chan, port)`, is an example of a *destructuring let*: the pattern separates
+a tuple into its component parts).
+
+~~~~
+let (port, chan): (Port<int>, Chan<int>) = Chan::new();
+~~~~
+
+The child task will use the channel to send data to the parent task,
+which will wait to receive the data on the port. The next statement
+spawns the child task.
+
+~~~~
+# use std::task::spawn;
+# fn some_expensive_computation() -> int { 42 }
+# let (port, chan) = Chan::new();
+do spawn || {
+    let result = some_expensive_computation();
+    chan.send(result);
+}
+~~~~
+
+Notice that the creation of the task closure transfers `chan` to the child
+task implicitly: the closure captures `chan` in its environment. Both `Chan`
+and `Port` are sendable types and may be captured into tasks or otherwise
+transferred between them. In the example, the child task runs an expensive
+computation, then sends the result over the captured channel.
+
+Finally, the parent continues with some other expensive
+computation, then waits for the child's result to arrive on the
+port:
+
+~~~~
+# fn some_other_expensive_computation() {}
+# let (port, chan) = Chan::<int>::new();
+# chan.send(0);
+some_other_expensive_computation();
+let result = port.recv();
+~~~~
+
+The `Port` and `Chan` pair created by `Chan::new` enables efficient
+communication between a single sender and a single receiver, but multiple
+senders cannot use a single `Chan`, and multiple receivers cannot use a single
+`Port`.  What if our example needed to compute multiple results across a number
+of tasks? The following program is ill-typed:
+
+~~~ {.xfail-test}
+# use std::task::{spawn};
+# fn some_expensive_computation() -> int { 42 }
+let (port, chan) = Chan::new();
+
+do spawn {
+    chan.send(some_expensive_computation());
+}
+
+// ERROR! The previous spawn statement already owns the channel,
+// so the compiler will not allow it to be captured again
+do spawn {
+    chan.send(some_expensive_computation());
+}
+~~~
+
+Instead we can use a `SharedChan`, a type that allows a single
+`Chan` to be shared by multiple senders.
+
+~~~
+# use std::task::spawn;
+
+let (port, chan) = SharedChan::new();
+
+for init_val in range(0u, 3) {
+    // Create a new channel handle to distribute to the child task
+    let child_chan = chan.clone();
+    do spawn {
+        child_chan.send(some_expensive_computation(init_val));
+    }
+}
+
+let result = port.recv() + port.recv() + port.recv();
+# fn some_expensive_computation(_i: uint) -> int { 42 }
+~~~
+
+Here we transfer ownership of the channel into a new `SharedChan` value.  Like
+`Chan`, `SharedChan` is a non-copyable, owned type (sometimes also referred to
+as an *affine* or *linear* type). Unlike with `Chan`, though, the programmer
+may duplicate a `SharedChan`, with the `clone()` method.  A cloned
+`SharedChan` produces a new handle to the same channel, allowing multiple
+tasks to send data to a single port.  Between `spawn`, `Chan` and
+`SharedChan`, we have enough tools to implement many useful concurrency
+patterns.
+
+Note that the above `SharedChan` example is somewhat contrived since
+you could also simply use three `Chan` pairs, but it serves to
+illustrate the point. For reference, written with multiple streams, it
+might look like the example below.
+
+~~~
+# use std::task::spawn;
+# use std::vec;
+
+// Create a vector of ports, one for each child task
+let ports = vec::from_fn(3, |init_val| {
+    let (port, chan) = Chan::new();
+    do spawn {
+        chan.send(some_expensive_computation(init_val));
+    }
+    port
+});
+
+// Wait on each port, accumulating the results
+let result = ports.iter().fold(0, |accum, port| accum + port.recv() );
+# fn some_expensive_computation(_i: uint) -> int { 42 }
+~~~
+
+## Backgrounding computations: Futures
+With `extra::future`, rust has a mechanism for requesting a computation and getting the result
+later.
+
+The basic example below illustrates this.
+~~~
+# fn make_a_sandwich() {};
+fn fib(n: u64) -> u64 {
+    // lengthy computation returning an uint
+    12586269025
+}
+
+let mut delayed_fib = extra::future::Future::spawn(proc() fib(50));
+make_a_sandwich();
+println!("fib(50) = {:?}", delayed_fib.get())
+~~~
+
+The call to `future::spawn` returns immediately a `future` object regardless of how long it
+takes to run `fib(50)`. You can then make yourself a sandwich while the computation of `fib` is
+running. The result of the execution of the method is obtained by calling `get` on the future.
+This call will block until the value is available (*i.e.* the computation is complete). Note that
+the future needs to be mutable so that it can save the result for next time `get` is called.
+
+Here is another example showing how futures allow you to background computations. The workload will
+be distributed on the available cores.
+~~~
+# use std::vec;
+fn partial_sum(start: uint) -> f64 {
+    let mut local_sum = 0f64;
+    for num in range(start*100000, (start+1)*100000) {
+        local_sum += (num as f64 + 1.0).pow(&-2.0);
+    }
+    local_sum
+}
+
+fn main() {
+    let mut futures = vec::from_fn(1000, |ind| do extra::future::Future::spawn { partial_sum(ind) });
+
+    let mut final_res = 0f64;
+    for ft in futures.mut_iter()  {
+        final_res += ft.get();
+    }
+    println!("π^2/6 is not far from : {}", final_res);
+}
+~~~
+
+## Sharing immutable data without copy: Arc
+
+To share immutable data between tasks, a first approach would be to only use pipes as we have seen
+previously. A copy of the data to share would then be made for each task. In some cases, this would
+add up to a significant amount of wasted memory and would require copying the same data more than
+necessary.
+
+To tackle this issue, one can use an Atomically Reference Counted wrapper (`Arc`) as implemented in
+the `extra` library of Rust. With an Arc, the data will no longer be copied for each task. The Arc
+acts as a reference to the shared data and only this reference is shared and cloned.
+
+Here is a small example showing how to use Arcs. We wish to run concurrently several computations on
+a single large vector of floats. Each task needs the full vector to perform its duty.
+~~~
+# use std::vec;
+# use std::rand;
+use extra::arc::Arc;
+
+fn pnorm(nums: &~[f64], p: uint) -> f64 {
+    nums.iter().fold(0.0, |a,b| a+(*b).pow(&(p as f64)) ).pow(&(1.0 / (p as f64)))
+}
+
+fn main() {
+    let numbers = vec::from_fn(1000000, |_| rand::random::<f64>());
+    println!("Inf-norm = {}",  *numbers.iter().max().unwrap());
+
+    let numbers_arc = Arc::new(numbers);
+
+    for num in range(1u, 10) {
+        let (port, chan)  = Chan::new();
+        chan.send(numbers_arc.clone());
+
+        do spawn {
+            let local_arc : Arc<~[f64]> = port.recv();
+            let task_numbers = local_arc.get();
+            println!("{}-norm = {}", num, pnorm(task_numbers, num));
+        }
+    }
+}
+~~~
+
+The function `pnorm` performs a simple computation on the vector (it computes the sum of its items
+at the power given as argument and takes the inverse power of this value). The Arc on the vector is
+created by the line
+~~~
+# use extra::arc::Arc;
+# use std::vec;
+# use std::rand;
+# let numbers = vec::from_fn(1000000, |_| rand::random::<f64>());
+let numbers_arc=Arc::new(numbers);
+~~~
+and a clone of it is sent to each task
+~~~
+# use extra::arc::Arc;
+# use std::vec;
+# use std::rand;
+# let numbers=vec::from_fn(1000000, |_| rand::random::<f64>());
+# let numbers_arc = Arc::new(numbers);
+# let (port, chan)  = Chan::new();
+chan.send(numbers_arc.clone());
+~~~
+copying only the wrapper and not its contents.
+
+Each task recovers the underlying data by
+~~~
+# use extra::arc::Arc;
+# use std::vec;
+# use std::rand;
+# let numbers=vec::from_fn(1000000, |_| rand::random::<f64>());
+# let numbers_arc=Arc::new(numbers);
+# let (port, chan)  = Chan::new();
+# chan.send(numbers_arc.clone());
+# let local_arc : Arc<~[f64]> = port.recv();
+let task_numbers = local_arc.get();
+~~~
+and can use it as if it were local.
+
+The `arc` module also implements Arcs around mutable data that are not covered here.
+
+# Handling task failure
+
+Rust has a built-in mechanism for raising exceptions. The `fail!()` macro
+(which can also be written with an error string as an argument: `fail!(
+~reason)`) and the `assert!` construct (which effectively calls `fail!()`
+if a boolean expression is false) are both ways to raise exceptions. When a
+task raises an exception the task unwinds its stack---running destructors and
+freeing memory along the way---and then exits. Unlike exceptions in C++,
+exceptions in Rust are unrecoverable within a single task: once a task fails,
+there is no way to "catch" the exception.
+
+While it isn't possible for a task to recover from failure, tasks may notify
+each other of failure. The simplest way of handling task failure is with the
+`try` function, which is similar to `spawn`, but immediately blocks waiting
+for the child task to finish. `try` returns a value of type `Result<T,
+()>`. `Result` is an `enum` type with two variants: `Ok` and `Err`. In this
+case, because the type arguments to `Result` are `int` and `()`, callers can
+pattern-match on a result to check whether it's an `Ok` result with an `int`
+field (representing a successful result) or an `Err` result (representing
+termination with an error).
+
+~~~{.xfail-test .linked-failure}
+# use std::task;
+# fn some_condition() -> bool { false }
+# fn calculate_result() -> int { 0 }
+let result: Result<int, ()> = do task::try {
+    if some_condition() {
+        calculate_result()
+    } else {
+        fail!("oops!");
+    }
+};
+assert!(result.is_err());
+~~~
+
+Unlike `spawn`, the function spawned using `try` may return a value,
+which `try` will dutifully propagate back to the caller in a [`Result`]
+enum. If the child task terminates successfully, `try` will
+return an `Ok` result; if the child task fails, `try` will return
+an `Error` result.
+
+[`Result`]: std/result/index.html
+
+> ***Note:*** A failed task does not currently produce a useful error
+> value (`try` always returns `Err(())`). In the
+> future, it may be possible for tasks to intercept the value passed to
+> `fail!()`.
+
+TODO: Need discussion of `future_result` in order to make failure
+modes useful.
+
+But not all failures are created equal. In some cases you might need to
+abort the entire program (perhaps you're writing an assert which, if
+it trips, indicates an unrecoverable logic error); in other cases you
+might want to contain the failure at a certain boundary (perhaps a
+small piece of input from the outside world, which you happen to be
+processing in parallel, is malformed and its processing task can't
+proceed).
+
+## Creating a task with a bi-directional communication path
+
+A very common thing to do is to spawn a child task where the parent
+and child both need to exchange messages with each other. The
+function `extra::comm::DuplexStream()` supports this pattern.  We'll
+look briefly at how to use it.
+
+To see how `DuplexStream()` works, we will create a child task
+that repeatedly receives a `uint` message, converts it to a string, and sends
+the string in response.  The child terminates when it receives `0`.
+Here is the function that implements the child task:
+
+~~~{.xfail-test .linked-failure}
+# use extra::comm::DuplexStream;
+# use std::uint;
+fn stringifier(channel: &DuplexStream<~str, uint>) {
+    let mut value: uint;
+    loop {
+        value = channel.recv();
+        channel.send(uint::to_str(value));
+        if value == 0 { break; }
+    }
+}
+~~~~
+
+The implementation of `DuplexStream` supports both sending and
+receiving. The `stringifier` function takes a `DuplexStream` that can
+send strings (the first type parameter) and receive `uint` messages
+(the second type parameter). The body itself simply loops, reading
+from the channel and then sending its response back.  The actual
+response itself is simply the stringified version of the received value,
+`uint::to_str(value)`.
+
+Here is the code for the parent task:
+
+~~~{.xfail-test .linked-failure}
+# use std::task::spawn;
+# use std::uint;
+# use extra::comm::DuplexStream;
+# fn stringifier(channel: &DuplexStream<~str, uint>) {
+#     let mut value: uint;
+#     loop {
+#         value = channel.recv();
+#         channel.send(uint::to_str(value));
+#         if value == 0u { break; }
+#     }
+# }
+# fn main() {
+
+let (from_child, to_child) = DuplexStream::new();
+
+do spawn {
+    stringifier(&to_child);
+};
+
+from_child.send(22);
+assert!(from_child.recv() == ~"22");
+
+from_child.send(23);
+from_child.send(0);
+
+assert!(from_child.recv() == ~"23");
+assert!(from_child.recv() == ~"0");
+
+# }
+~~~~
+
+The parent task first calls `DuplexStream` to create a pair of bidirectional
+endpoints. It then uses `task::spawn` to create the child task, which captures
+one end of the communication channel.  As a result, both parent and child can
+send and receive data to and from the other.
diff --git a/doc/guide-testing.md b/doc/guide-testing.md
new file mode 100644 (file)
index 0000000..dce60f1
--- /dev/null
@@ -0,0 +1,263 @@
+% Rust Testing Guide
+
+# Quick start
+
+To create test functions, add a `#[test]` attribute like this:
+
+```rust
+fn return_two() -> int {
+    2
+}
+
+#[test]
+fn return_two_test() {
+    let x = return_two();
+    assert!(x == 2);
+}
+```
+
+To run these tests, use `rustc --test`:
+
+```
+$ rustc --test foo.rs; ./foo
+running 1 test
+test return_two_test ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
+```
+
+`rustc foo.rs` will *not* compile the tests, since `#[test]` implies
+`#[cfg(test)]`. The `--test` flag to `rustc` implies `--cfg test`.
+
+
+# Unit testing in Rust
+
+Rust has built in support for simple unit testing. Functions can be
+marked as unit tests using the 'test' attribute.
+
+```rust
+#[test]
+fn return_none_if_empty() {
+    // ... test code ...
+}
+```
+
+A test function's signature must have no arguments and no return
+value. To run the tests in a crate, it must be compiled with the
+'--test' flag: `rustc myprogram.rs --test -o myprogram-tests`. Running
+the resulting executable will run all the tests in the crate. A test
+is considered successful if its function returns; if the task running
+the test fails, through a call to `fail!`, a failed `check` or
+`assert`, or some other (`assert_eq`, `assert_approx_eq`, ...) means,
+then the test fails.
+
+When compiling a crate with the '--test' flag '--cfg test' is also
+implied, so that tests can be conditionally compiled.
+
+```rust
+#[cfg(test)]
+mod tests {
+    #[test]
+    fn return_none_if_empty() {
+      // ... test code ...
+    }
+}
+```
+
+Additionally #[test] items behave as if they also have the
+#[cfg(test)] attribute, and will not be compiled when the --test flag
+is not used.
+
+Tests that should not be run can be annotated with the 'ignore'
+attribute. The existence of these tests will be noted in the test
+runner output, but the test will not be run. Tests can also be ignored
+by configuration so, for example, to ignore a test on windows you can
+write `#[ignore(cfg(target_os = "win32"))]`.
+
+Tests that are intended to fail can be annotated with the
+'should_fail' attribute. The test will be run, and if it causes its
+task to fail then the test will be counted as successful; otherwise it
+will be counted as a failure. For example:
+
+```rust
+#[test]
+#[should_fail]
+fn test_out_of_bounds_failure() {
+    let v: [int] = [];
+    v[0];
+}
+```
+
+A test runner built with the '--test' flag supports a limited set of
+arguments to control which tests are run: the first free argument
+passed to a test runner specifies a filter used to narrow down the set
+of tests being run; the '--ignored' flag tells the test runner to run
+only tests with the 'ignore' attribute.
+
+## Parallelism
+
+By default, tests are run in parallel, which can make interpreting
+failure output difficult. In these cases you can set the
+`RUST_TEST_TASKS` environment variable to 1 to make the tests run
+sequentially.
+
+## Benchmarking
+
+The test runner also understands a simple form of benchmark execution.
+Benchmark functions are marked with the `#[bench]` attribute, rather
+than `#[test]`, and have a different form and meaning. They are
+compiled along with `#[test]` functions when a crate is compiled with
+`--test`, but they are not run by default. To run the benchmark
+component of your testsuite, pass `--bench` to the compiled test
+runner.
+
+The type signature of a benchmark function differs from a unit test:
+it takes a mutable reference to type `test::BenchHarness`. Inside the
+benchmark function, any time-variable or "setup" code should execute
+first, followed by a call to `iter` on the benchmark harness, passing
+a closure that contains the portion of the benchmark you wish to
+actually measure the per-iteration speed of.
+
+For benchmarks relating to processing/generating data, one can set the
+`bytes` field to the number of bytes consumed/produced in each
+iteration; this will used to show the throughput of the benchmark.
+This must be the amount used in each iteration, *not* the total
+amount.
+
+For example:
+
+```rust
+extern mod extra;
+use std::vec;
+
+#[bench]
+fn bench_sum_1024_ints(b: &mut extra::test::BenchHarness) {
+    let v = vec::from_fn(1024, |n| n);
+    b.iter(|| {v.iter().fold(0, |old, new| old + *new);} );
+}
+
+#[bench]
+fn initialise_a_vector(b: &mut extra::test::BenchHarness) {
+    b.iter(|| {vec::from_elem(1024, 0u64);} );
+    b.bytes = 1024 * 8;
+}
+```
+
+The benchmark runner will calibrate measurement of the benchmark
+function to run the `iter` block "enough" times to get a reliable
+measure of the per-iteration speed.
+
+Advice on writing benchmarks:
+
+  - Move setup code outside the `iter` loop; only put the part you
+    want to measure inside
+  - Make the code do "the same thing" on each iteration; do not
+    accumulate or change state
+  - Make the outer function idempotent too; the benchmark runner is
+    likely to run it many times
+  - Make the inner `iter` loop short and fast so benchmark runs are
+    fast and the calibrator can adjust the run-length at fine
+    resolution
+  - Make the code in the `iter` loop do something simple, to assist in
+    pinpointing performance improvements (or regressions)
+
+To run benchmarks, pass the `--bench` flag to the compiled
+test-runner. Benchmarks are compiled-in but not executed by default.
+
+## Examples
+
+### Typical test run
+
+```
+> mytests
+
+running 30 tests
+running driver::tests::mytest1 ... ok
+running driver::tests::mytest2 ... ignored
+... snip ...
+running driver::tests::mytest30 ... ok
+
+result: ok. 28 passed; 0 failed; 2 ignored
+```
+
+### Test run with failures
+
+```
+> mytests
+
+running 30 tests
+running driver::tests::mytest1 ... ok
+running driver::tests::mytest2 ... ignored
+... snip ...
+running driver::tests::mytest30 ... FAILED
+
+result: FAILED. 27 passed; 1 failed; 2 ignored
+```
+
+### Running ignored tests
+
+```
+> mytests --ignored
+
+running 2 tests
+running driver::tests::mytest2 ... failed
+running driver::tests::mytest10 ... ok
+
+result: FAILED. 1 passed; 1 failed; 0 ignored
+```
+
+### Running a subset of tests
+
+```
+> mytests mytest1
+
+running 11 tests
+running driver::tests::mytest1 ... ok
+running driver::tests::mytest10 ... ignored
+... snip ...
+running driver::tests::mytest19 ... ok
+
+result: ok. 11 passed; 0 failed; 1 ignored
+```
+
+### Running benchmarks
+
+```
+> mytests --bench
+
+running 2 tests
+test bench_sum_1024_ints ... bench: 709 ns/iter (+/- 82)
+test initialise_a_vector ... bench: 424 ns/iter (+/- 99) = 19320 MB/s
+
+test result: ok. 0 passed; 0 failed; 0 ignored; 2 measured
+```
+
+## Saving and ratcheting metrics
+
+When running benchmarks or other tests, the test runner can record
+per-test "metrics". Each metric is a scalar `f64` value, plus a noise
+value which represents uncertainty in the measurement. By default, all
+`#[bench]` benchmarks are recorded as metrics, which can be saved as
+JSON in an external file for further reporting.
+
+In addition, the test runner supports _ratcheting_ against a metrics
+file. Ratcheting is like saving metrics, except that after each run,
+if the output file already exists the results of the current run are
+compared against the contents of the existing file, and any regression
+_causes the testsuite to fail_. If the comparison passes -- if all
+metrics stayed the same (within noise) or improved -- then the metrics
+file is overwritten with the new values. In this way, a metrics file
+in your workspace can be used to ensure your work does not regress
+performance.
+
+Test runners take 3 options that are relevant to metrics:
+
+  - `--save-metrics=<file.json>` will save the metrics from a test run
+    to `file.json`
+  - `--ratchet-metrics=<file.json>` will ratchet the metrics against
+    the `file.json`
+  - `--ratchet-noise-percent=N` will override the noise measurements
+    in `file.json`, and consider a metric change less than `N%` to be
+    noise. This can be helpful if you are testing in a noisy
+    environment where the benchmark calibration loop cannot acquire a
+    clear enough signal.
diff --git a/doc/tutorial-borrowed-ptr.md b/doc/tutorial-borrowed-ptr.md
deleted file mode 100644 (file)
index c5933eb..0000000
+++ /dev/null
@@ -1,663 +0,0 @@
-% Rust Borrowed Pointers Tutorial
-
-# Introduction
-
-Borrowed pointers are one of the more flexible and powerful tools available in
-Rust. A borrowed pointer can point anywhere: into the managed or exchange
-heap, into the stack, and even into the interior of another data structure. A
-borrowed pointer is as flexible as a C pointer or C++ reference. However,
-unlike C and C++ compilers, the Rust compiler includes special static checks
-that ensure that programs use borrowed pointers safely. Another advantage of
-borrowed pointers is that they are invisible to the garbage collector, so
-working with borrowed pointers helps reduce the overhead of automatic memory
-management.
-
-Despite their complete safety, a borrowed pointer's representation at runtime
-is the same as that of an ordinary pointer in a C program. They introduce zero
-overhead. The compiler does all safety checks at compile time.
-
-Although borrowed pointers have rather elaborate theoretical
-underpinnings (region pointers), the core concepts will be familiar to
-anyone who has worked with C or C++. Therefore, the best way to explain
-how they are used—and their limitations—is probably just to work
-through several examples.
-
-# By example
-
-Borrowed pointers are called *borrowed* because they are only valid for
-a limited duration. Borrowed pointers never claim any kind of ownership
-over the data that they point to: instead, they are used for cases
-where you would like to use data for a short time.
-
-As an example, consider a simple struct type `Point`:
-
-~~~
-struct Point {x: f64, y: f64}
-~~~
-
-We can use this simple definition to allocate points in many different ways. For
-example, in this code, each of these three local variables contains a
-point, but allocated in a different place:
-
-~~~
-# struct Point {x: f64, y: f64}
-let on_the_stack :  Point =  Point {x: 3.0, y: 4.0};
-let managed_box  : @Point = @Point {x: 5.0, y: 1.0};
-let owned_box    : ~Point = ~Point {x: 7.0, y: 9.0};
-~~~
-
-Suppose we wanted to write a procedure that computed the distance between any
-two points, no matter where they were stored. For example, we might like to
-compute the distance between `on_the_stack` and `managed_box`, or between
-`managed_box` and `owned_box`. One option is to define a function that takes
-two arguments of type `Point`—that is, it takes the points by value. But if we
-define it this way, calling the function will cause the points to be
-copied. For points, this is probably not so bad, but often copies are
-expensive. Worse, if the data type contains mutable fields, copying can change
-the semantics of your program in unexpected ways. So we'd like to define a
-function that takes the points by pointer. We can use borrowed pointers to do
-this:
-
-~~~
-# struct Point {x: f64, y: f64}
-# fn sqrt(f: f64) -> f64 { 0.0 }
-fn compute_distance(p1: &Point, p2: &Point) -> f64 {
-    let x_d = p1.x - p2.x;
-    let y_d = p1.y - p2.y;
-    sqrt(x_d * x_d + y_d * y_d)
-}
-~~~
-
-Now we can call `compute_distance()` in various ways:
-
-~~~
-# struct Point {x: f64, y: f64}
-# let on_the_stack :  Point =  Point{x: 3.0, y: 4.0};
-# let managed_box  : @Point = @Point{x: 5.0, y: 1.0};
-# let owned_box    : ~Point = ~Point{x: 7.0, y: 9.0};
-# fn compute_distance(p1: &Point, p2: &Point) -> f64 { 0.0 }
-compute_distance(&on_the_stack, managed_box);
-compute_distance(managed_box, owned_box);
-~~~
-
-Here, the `&` operator takes the address of the variable
-`on_the_stack`; this is because `on_the_stack` has the type `Point`
-(that is, a struct value) and we have to take its address to get a
-value. We also call this _borrowing_ the local variable
-`on_the_stack`, because we have created an alias: that is, another
-name for the same data.
-
-In contrast, we can pass the boxes `managed_box` and `owned_box` to
-`compute_distance` directly. The compiler automatically converts a box like
-`@Point` or `~Point` to a borrowed pointer like `&Point`. This is another form
-of borrowing: in this case, the caller lends the contents of the managed or
-owned box to the callee.
-
-Whenever a caller lends data to a callee, there are some limitations on what
-the caller can do with the original. For example, if the contents of a
-variable have been lent out, you cannot send that variable to another task. In
-addition, the compiler will reject any code that might cause the borrowed
-value to be freed or overwrite its component fields with values of different
-types (I'll get into what kinds of actions those are shortly). This rule
-should make intuitive sense: you must wait for a borrower to return the value
-that you lent it (that is, wait for the borrowed pointer to go out of scope)
-before you can make full use of it again.
-
-# Other uses for the & operator
-
-In the previous example, the value `on_the_stack` was defined like so:
-
-~~~
-# struct Point {x: f64, y: f64}
-let on_the_stack: Point = Point {x: 3.0, y: 4.0};
-~~~
-
-This declaration means that code can only pass `Point` by value to other
-functions. As a consequence, we had to explicitly take the address of
-`on_the_stack` to get a borrowed pointer. Sometimes however it is more
-convenient to move the & operator into the definition of `on_the_stack`:
-
-~~~
-# struct Point {x: f64, y: f64}
-let on_the_stack2: &Point = &Point {x: 3.0, y: 4.0};
-~~~
-
-Applying `&` to an rvalue (non-assignable location) is just a convenient
-shorthand for creating a temporary and taking its address. A more verbose
-way to write the same code is:
-
-~~~
-# struct Point {x: f64, y: f64}
-let tmp = Point {x: 3.0, y: 4.0};
-let on_the_stack2 : &Point = &tmp;
-~~~
-
-# Taking the address of fields
-
-As in C, the `&` operator is not limited to taking the address of
-local variables. It can also take the address of fields or
-individual array elements. For example, consider this type definition
-for `rectangle`:
-
-~~~
-struct Point {x: f64, y: f64} // as before
-struct Size {w: f64, h: f64} // as before
-struct Rectangle {origin: Point, size: Size}
-~~~
-
-Now, as before, we can define rectangles in a few different ways:
-
-~~~
-# struct Point {x: f64, y: f64}
-# struct Size {w: f64, h: f64} // as before
-# struct Rectangle {origin: Point, size: Size}
-let rect_stack   = &Rectangle {origin: Point {x: 1.0, y: 2.0},
-                               size: Size {w: 3.0, h: 4.0}};
-let rect_managed = @Rectangle {origin: Point {x: 3.0, y: 4.0},
-                               size: Size {w: 3.0, h: 4.0}};
-let rect_owned   = ~Rectangle {origin: Point {x: 5.0, y: 6.0},
-                               size: Size {w: 3.0, h: 4.0}};
-~~~
-
-In each case, we can extract out individual subcomponents with the `&`
-operator. For example, I could write:
-
-~~~
-# struct Point {x: f64, y: f64} // as before
-# struct Size {w: f64, h: f64} // as before
-# struct Rectangle {origin: Point, size: Size}
-# let rect_stack  = &Rectangle {origin: Point {x: 1.0, y: 2.0}, size: Size {w: 3.0, h: 4.0}};
-# let rect_managed = @Rectangle {origin: Point {x: 3.0, y: 4.0}, size: Size {w: 3.0, h: 4.0}};
-# let rect_owned = ~Rectangle {origin: Point {x: 5.0, y: 6.0}, size: Size {w: 3.0, h: 4.0}};
-# fn compute_distance(p1: &Point, p2: &Point) -> f64 { 0.0 }
-compute_distance(&rect_stack.origin, &rect_managed.origin);
-~~~
-
-which would borrow the field `origin` from the rectangle on the stack
-as well as from the managed box, and then compute the distance between them.
-
-# Borrowing managed boxes and rooting
-
-We’ve seen a few examples so far of borrowing heap boxes, both managed
-and owned. Up till this point, we’ve glossed over issues of
-safety. As stated in the introduction, at runtime a borrowed pointer
-is simply a pointer, nothing more. Therefore, avoiding C's problems
-with dangling pointers requires a compile-time safety check.
-
-The basis for the check is the notion of _lifetimes_. A lifetime is a
-static approximation of the span of execution during which the pointer
-is valid: it always corresponds to some expression or block within the
-program. Code inside that expression can use the pointer without
-restrictions. But if the pointer escapes from that expression (for
-example, if the expression contains an assignment expression that
-assigns the pointer to a mutable field of a data structure with a
-broader scope than the pointer itself), the compiler reports an
-error. We'll be discussing lifetimes more in the examples to come, and
-a more thorough introduction is also available.
-
-When the `&` operator creates a borrowed pointer, the compiler must
-ensure that the pointer remains valid for its entire
-lifetime. Sometimes this is relatively easy, such as when taking the
-address of a local variable or a field that is stored on the stack:
-
-~~~
-struct X { f: int }
-fn example1() {
-    let mut x = X { f: 3 };
-    let y = &mut x.f;  // -+ L
-    ...                //  |
-}                      // -+
-~~~
-
-Here, the lifetime of the borrowed pointer `y` is simply L, the
-remainder of the function body. The compiler need not do any other
-work to prove that code will not free `x.f`. This is true even if the
-code mutates `x`.
-
-The situation gets more complex when borrowing data inside heap boxes:
-
-~~~
-# struct X { f: int }
-fn example2() {
-    let mut x = @X { f: 3 };
-    let y = &x.f;      // -+ L
-    ...                //  |
-}                      // -+
-~~~
-
-In this example, the value `x` is a heap box, and `y` is therefore a
-pointer into that heap box. Again the lifetime of `y` is L, the
-remainder of the function body. But there is a crucial difference:
-suppose `x` were to be reassigned during the lifetime L? If the
-compiler isn't careful, the managed box could become *unrooted*, and
-would therefore be subject to garbage collection. A heap box that is
-unrooted is one such that no pointer values in the heap point to
-it. It would violate memory safety for the box that was originally
-assigned to `x` to be garbage-collected, since a non-heap
-pointer *`y`* still points into it.
-
-> ***Note:*** Our current implementation implements the garbage collector
-> using reference counting and cycle detection.
-
-For this reason, whenever an `&` expression borrows the interior of a
-managed box stored in a mutable location, the compiler inserts a
-temporary that ensures that the managed box remains live for the
-entire lifetime. So, the above example would be compiled as if it were
-written
-
-~~~
-# struct X { f: int }
-fn example2() {
-    let mut x = @X {f: 3};
-    let x1 = x;
-    let y = &x1.f;     // -+ L
-    ...                //  |
-}                      // -+
-~~~
-
-Now if `x` is reassigned, the pointer `y` will still remain valid. This
-process is called *rooting*.
-
-# Borrowing owned boxes
-
-The previous example demonstrated *rooting*, the process by which the
-compiler ensures that managed boxes remain live for the duration of a
-borrow. Unfortunately, rooting does not work for borrows of owned
-boxes, because it is not possible to have two references to a owned
-box.
-
-For owned boxes, therefore, the compiler will only allow a borrow *if
-the compiler can guarantee that the owned box will not be reassigned
-or moved for the lifetime of the pointer*. This does not necessarily
-mean that the owned box is stored in immutable memory. For example,
-the following function is legal:
-
-~~~
-# fn some_condition() -> bool { true }
-# struct Foo { f: int }
-fn example3() -> int {
-    let mut x = ~Foo {f: 3};
-    if some_condition() {
-        let y = &x.f;      // -+ L
-        return *y;         //  |
-    }                      // -+
-    x = ~Foo {f: 4};
-    ...
-# return 0;
-}
-~~~
-
-Here, as before, the interior of the variable `x` is being borrowed
-and `x` is declared as mutable. However, the compiler can prove that
-`x` is not assigned anywhere in the lifetime L of the variable
-`y`. Therefore, it accepts the function, even though `x` is mutable
-and in fact is mutated later in the function.
-
-It may not be clear why we are so concerned about mutating a borrowed
-variable. The reason is that the runtime system frees any owned box
-_as soon as its owning reference changes or goes out of
-scope_. Therefore, a program like this is illegal (and would be
-rejected by the compiler):
-
-~~~ {.xfail-test}
-fn example3() -> int {
-    let mut x = ~X {f: 3};
-    let y = &x.f;
-    x = ~X {f: 4};  // Error reported here.
-    *y
-}
-~~~
-
-To make this clearer, consider this diagram showing the state of
-memory immediately before the re-assignment of `x`:
-
-~~~ {.notrust}
-    Stack               Exchange Heap
-
-  x +----------+
-    | ~{f:int} | ----+
-  y +----------+     |
-    | &int     | ----+
-    +----------+     |    +---------+
-                     +--> |  f: 3   |
-                          +---------+
-~~~
-
-Once the reassignment occurs, the memory will look like this:
-
-~~~ {.notrust}
-    Stack               Exchange Heap
-
-  x +----------+          +---------+
-    | ~{f:int} | -------> |  f: 4   |
-  y +----------+          +---------+
-    | &int     | ----+
-    +----------+     |    +---------+
-                     +--> | (freed) |
-                          +---------+
-~~~
-
-Here you can see that the variable `y` still points at the old box,
-which has been freed.
-
-In fact, the compiler can apply the same kind of reasoning to any
-memory that is _(uniquely) owned by the stack frame_. So we could
-modify the previous example to introduce additional owned pointers
-and structs, and the compiler will still be able to detect possible
-mutations:
-
-~~~ {.xfail-test}
-fn example3() -> int {
-    struct R { g: int }
-    struct S { f: ~R }
-
-    let mut x = ~S {f: ~R {g: 3}};
-    let y = &x.f.g;
-    x = ~S {f: ~R {g: 4}};  // Error reported here.
-    x.f = ~R {g: 5};        // Error reported here.
-    *y
-}
-~~~
-
-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`.
-
-# Borrowing and enums
-
-The previous example showed that the type system forbids any borrowing
-of owned boxes found in aliasable, mutable memory. This restriction
-prevents pointers from pointing into freed memory. There is one other
-case where the compiler must be very careful to ensure that pointers
-remain valid: pointers into the interior of an `enum`.
-
-As an example, let’s look at the following `shape` type that can
-represent both rectangles and circles:
-
-~~~
-struct Point {x: f64, y: f64}; // as before
-struct Size {w: f64, h: f64}; // as before
-enum Shape {
-    Circle(Point, f64),   // origin, radius
-    Rectangle(Point, Size)  // upper-left, dimensions
-}
-~~~
-
-Now we might write a function to compute the area of a shape. This
-function takes a borrowed pointer to a shape, to avoid the need for
-copying.
-
-~~~
-# struct Point {x: f64, y: f64}; // as before
-# struct Size {w: f64, h: f64}; // as before
-# enum Shape {
-#     Circle(Point, f64),   // origin, radius
-#     Rectangle(Point, Size)  // upper-left, dimensions
-# }
-# static tau: f64 = 6.28;
-fn compute_area(shape: &Shape) -> f64 {
-    match *shape {
-        Circle(_, radius) => 0.5 * tau * radius * radius,
-        Rectangle(_, ref size) => size.w * size.h
-    }
-}
-~~~
-
-The first case matches against circles. Here, the pattern extracts the
-radius from the shape variant and the action uses it to compute the
-area of the circle. (Like any up-to-date engineer, we use the [tau
-circle constant][tau] and not that dreadfully outdated notion of pi).
-
-[tau]: http://www.math.utah.edu/~palais/pi.html
-
-The second match is more interesting. Here we match against a
-rectangle and extract its size: but rather than copy the `size`
-struct, we use a by-reference binding to create a pointer to it. In
-other words, a pattern binding like `ref size` binds the name `size`
-to a pointer of type `&size` into the _interior of the enum_.
-
-To make this more clear, let's look at a diagram of memory layout in
-the case where `shape` points at a rectangle:
-
-~~~ {.notrust}
-Stack             Memory
-
-+-------+         +---------------+
-| shape | ------> | rectangle(    |
-+-------+         |   {x: f64,    |
-| size  | -+      |    y: f64},   |
-+-------+  +----> |   {w: f64,    |
-                  |    h: f64})   |
-                  +---------------+
-~~~
-
-Here you can see that rectangular shapes are composed of five words of
-memory. The first is a tag indicating which variant this enum is
-(`rectangle`, in this case). The next two words are the `x` and `y`
-fields for the point and the remaining two are the `w` and `h` fields
-for the size. The binding `size` is then a pointer into the inside of
-the shape.
-
-Perhaps you can see where the danger lies: if the shape were somehow
-to be reassigned, perhaps to a circle, then although the memory used
-to store that shape value would still be valid, _it would have a
-different type_! The following diagram shows what memory would look
-like if code overwrote `shape` with a circle:
-
-~~~ {.notrust}
-Stack             Memory
-
-+-------+         +---------------+
-| shape | ------> | circle(       |
-+-------+         |   {x: f64,    |
-| size  | -+      |    y: f64},   |
-+-------+  +----> |   f64)        |
-                  |               |
-                  +---------------+
-~~~
-
-As you can see, the `size` pointer would be pointing at a `f64`
-instead of a struct. This is not good: dereferencing the second field
-of a `f64` as if it were a struct with two fields would be a memory
-safety violation.
-
-So, in fact, for every `ref` binding, the compiler will impose the
-same rules as the ones we saw for borrowing the interior of a owned
-box: it must be able to guarantee that the `enum` will not be
-overwritten for the duration of the borrow.  In fact, the compiler
-would accept the example we gave earlier. The example is safe because
-the shape pointer has type `&Shape`, which means "borrowed pointer to
-immutable memory containing a `shape`". If, however, the type of that
-pointer were `&mut Shape`, then the ref binding would be ill-typed.
-Just as with owned boxes, the compiler will 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.
-
-# Returning borrowed pointers
-
-So far, all of the examples we have looked at, use borrowed pointers in a
-“downward” direction. That is, a method or code block creates a
-borrowed pointer, then uses it within the same scope. It is also
-possible to return borrowed pointers as the result of a function, but
-as we'll see, doing so requires some explicit annotation.
-
-For example, we could write a subroutine like this:
-
-~~~
-struct Point {x: f64, y: f64}
-fn get_x<'r>(p: &'r Point) -> &'r f64 { &p.x }
-~~~
-
-Here, the function `get_x()` returns a pointer into the structure it
-was given. The type of the parameter (`&'r Point`) and return type
-(`&'r f64`) both use a new syntactic form that we have not seen so
-far.  Here the identifier `r` names the lifetime of the pointer
-explicitly. So in effect, this function declares that it takes a
-pointer with lifetime `r` and returns a pointer with that same
-lifetime.
-
-In general, it is only possible to return borrowed pointers if they
-are derived from a parameter to the procedure. In that case, the
-pointer result will always have the same lifetime as one of the
-parameters; named lifetimes indicate which parameter that
-is.
-
-In the previous examples, function parameter types did not include a
-lifetime name. In those examples, the compiler simply creates a fresh
-name for the lifetime automatically: that is, the lifetime name is
-guaranteed to refer to a distinct lifetime from the lifetimes of all
-other parameters.
-
-Named lifetimes that appear in function signatures are conceptually
-the same as the other lifetimes we have seen before, but they are a bit
-abstract: they don’t refer to a specific expression within `get_x()`,
-but rather to some expression within the *caller of `get_x()`*.  The
-lifetime `r` is actually a kind of *lifetime parameter*: it is defined
-by the caller to `get_x()`, just as the value for the parameter `p` is
-defined by that caller.
-
-In any case, whatever the lifetime of `r` is, the pointer produced by
-`&p.x` always has the same lifetime as `p` itself: a pointer to a
-field of a struct is valid as long as the struct is valid. Therefore,
-the compiler accepts the function `get_x()`.
-
-To emphasize this point, let’s look at a variation on the example, this
-time one that does not compile:
-
-~~~ {.xfail-test}
-struct Point {x: f64, y: f64}
-fn get_x_sh(p: @Point) -> &f64 {
-    &p.x // Error reported here
-}
-~~~
-
-Here, the function `get_x_sh()` takes a managed box as input and
-returns a borrowed pointer. As before, the lifetime of the borrowed
-pointer that will be returned is a parameter (specified by the
-caller). That means that `get_x_sh()` promises to return a borrowed
-pointer that is valid for as long as the caller would like: this is
-subtly different from the first example, which promised to return a
-pointer that was valid for as long as its pointer argument was valid.
-
-Within `get_x_sh()`, we see the expression `&p.x` which takes the
-address of a field of a managed box. The presence of this expression
-implies that the compiler must guarantee that, so long as the
-resulting pointer is valid, the managed box will not be reclaimed by
-the garbage collector. But recall that `get_x_sh()` also promised to
-return a pointer that was valid for as long as the caller wanted it to
-be. Clearly, `get_x_sh()` is not in a position to make both of these
-guarantees; in fact, it cannot guarantee that the pointer will remain
-valid at all once it returns, as the parameter `p` may or may not be
-live in the caller. Therefore, the compiler will report an error here.
-
-In general, if you borrow a managed (or owned) box to create a
-borrowed pointer, the pointer will only be valid within the function
-and cannot be returned. This is why the typical way to return borrowed
-pointers is to take borrowed pointers as input (the only other case in
-which it can be legal to return a borrowed pointer is if the pointer
-points at a static constant).
-
-# Named lifetimes
-
-Let's look at named lifetimes in more detail. Named lifetimes allow
-for grouping of parameters by lifetime. For example, consider this
-function:
-
-~~~
-# struct Point {x: f64, y: f64}; // as before
-# struct Size {w: f64, h: f64}; // as before
-# enum Shape {
-#     Circle(Point, f64),   // origin, radius
-#     Rectangle(Point, Size)  // upper-left, dimensions
-# }
-# fn compute_area(shape: &Shape) -> f64 { 0.0 }
-fn select<'r, T>(shape: &'r Shape, threshold: f64,
-                 a: &'r T, b: &'r T) -> &'r T {
-    if compute_area(shape) > threshold {a} else {b}
-}
-~~~
-
-This function takes three borrowed pointers and assigns each the same
-lifetime `r`.  In practice, this means that, in the caller, the
-lifetime `r` will be the *intersection of the lifetime of the three
-region parameters*. This may be overly conservative, as in this
-example:
-
-~~~
-# struct Point {x: f64, y: f64}; // as before
-# struct Size {w: f64, h: f64}; // as before
-# enum Shape {
-#     Circle(Point, f64),   // origin, radius
-#     Rectangle(Point, Size)  // upper-left, dimensions
-# }
-# fn compute_area(shape: &Shape) -> f64 { 0.0 }
-# fn select<'r, T>(shape: &Shape, threshold: f64,
-#                  a: &'r T, b: &'r T) -> &'r T {
-#     if compute_area(shape) > threshold {a} else {b}
-# }
-                                                     // -+ r
-fn select_based_on_unit_circle<'r, T>(               //  |-+ B
-    threshold: f64, a: &'r T, b: &'r T) -> &'r T { //  | |
-                                                     //  | |
-    let shape = Circle(Point {x: 0., y: 0.}, 1.);    //  | |
-    select(&shape, threshold, a, b)                  //  | |
-}                                                    //  |-+
-                                                     // -+
-~~~
-
-In this call to `select()`, the lifetime of the first parameter shape
-is B, the function body. Both of the second two parameters `a` and `b`
-share the same lifetime, `r`, which is a lifetime parameter of
-`select_based_on_unit_circle()`. The caller will infer the
-intersection of these two lifetimes as the lifetime of the returned
-value, and hence the return value of `select()` will be assigned a
-lifetime of B. This will in turn lead to a compilation error, because
-`select_based_on_unit_circle()` is supposed to return a value with the
-lifetime `r`.
-
-To address this, we can modify the definition of `select()` to
-distinguish the lifetime of the first parameter from the lifetime of
-the latter two. After all, the first parameter is not being
-returned. Here is how the new `select()` might look:
-
-~~~
-# struct Point {x: f64, y: f64}; // as before
-# struct Size {w: f64, h: f64}; // as before
-# enum Shape {
-#     Circle(Point, f64),   // origin, radius
-#     Rectangle(Point, Size)  // upper-left, dimensions
-# }
-# fn compute_area(shape: &Shape) -> f64 { 0.0 }
-fn select<'r, 'tmp, T>(shape: &'tmp Shape, threshold: f64,
-                       a: &'r T, b: &'r T) -> &'r T {
-    if compute_area(shape) > threshold {a} else {b}
-}
-~~~
-
-Here you can see that `shape`'s lifetime is now named `tmp`. The
-parameters `a`, `b`, and the return value all have the lifetime `r`.
-However, since the lifetime `tmp` is not returned, it would be more
-concise to just omit the named lifetime for `shape` altogether:
-
-~~~
-# struct Point {x: f64, y: f64}; // as before
-# struct Size {w: f64, h: f64}; // as before
-# enum Shape {
-#     Circle(Point, f64),   // origin, radius
-#     Rectangle(Point, Size)  // upper-left, dimensions
-# }
-# fn compute_area(shape: &Shape) -> f64 { 0.0 }
-fn select<'r, T>(shape: &Shape, threshold: f64,
-                 a: &'r T, b: &'r T) -> &'r T {
-    if compute_area(shape) > threshold {a} else {b}
-}
-~~~
-
-This is equivalent to the previous definition.
-
-# Conclusion
-
-So there you have it: a (relatively) brief tour of the borrowed pointer
-system. For more details, we refer to the (yet to be written) reference
-document on borrowed pointers, which will explain the full notation
-and give more examples.
diff --git a/doc/tutorial-conditions.md b/doc/tutorial-conditions.md
deleted file mode 100644 (file)
index 52894c0..0000000
+++ /dev/null
@@ -1,858 +0,0 @@
-% Rust Condition and Error-handling Tutorial
-
-# Introduction
-
-Rust does not provide exception handling[^why-no-exceptions]
-in the form most commonly seen in other programming languages such as C++ or Java.
-Instead, it provides four mechanisms that work together to handle errors or other rare events.
-The four mechanisms are:
-
-  - Options
-  - Results
-  - Failure
-  - Conditions
-
-This tutorial will lead you through use of these mechanisms
-in order to understand the trade-offs of each and relationships between them.
-
-# Example program
-
-This tutorial will be based around an example program
-that attempts to read lines from a file
-consisting of pairs of numbers,
-and then print them back out with slightly different formatting.
-The input to the program might look like this:
-
-~~~~ {.notrust}
-$ cat numbers.txt
-1 2
-34 56
-789 123
-45 67
-~~~~
-
-For which the intended output looks like this:
-
-~~~~ {.notrust}
-$ ./example numbers.txt
-0001, 0002
-0034, 0056
-0789, 0123
-0045, 0067
-~~~~
-
-An example program that does this task reads like this:
-
-~~~~
-# #[allow(unused_imports)];
-# extern mod extra;
-use std::io::buffered::BufferedReader;
-use std::io::File;
-# mod BufferedReader {
-#     use std::io::File;
-#     use std::io::mem::MemReader;
-#     use std::io::buffered::BufferedReader;
-#     static s : &'static [u8] = bytes!("1 2\n\
-#                                        34 56\n\
-#                                        789 123\n\
-#                                        45 67\n\
-#                                        ");
-#     pub fn new(_inner: Option<File>) -> BufferedReader<MemReader> {
-#           BufferedReader::new(MemReader::new(s.to_owned()))
-#     }
-# }
-
-fn main() {
-    let pairs = read_int_pairs();
-    for &(a,b) in pairs.iter() {
-        println!("{:4.4d}, {:4.4d}", a, b);
-    }
-}
-
-fn read_int_pairs() -> ~[(int,int)] {
-    let mut pairs = ~[];
-
-    // Path takes a generic by-value, rather than by reference
-#    let _g = std::io::ignore_io_error();
-    let path = Path::new(&"foo.txt");
-    let mut reader = BufferedReader::new(File::open(&path));
-
-    // 1. Iterate over the lines of our file.
-    for line in reader.lines() {
-        // 2. Split the line into fields ("words").
-        let fields = line.words().to_owned_vec();
-        // 3. Match the vector of fields against a vector pattern.
-        match fields {
-
-            // 4. When the line had two fields:
-            [a, b] => {
-                // 5. Try parsing both fields as ints.
-                match (from_str::<int>(a), from_str::<int>(b)) {
-
-                    // 6. If parsing succeeded for both, push both.
-                    (Some(a), Some(b)) => pairs.push((a,b)),
-                    // 7. Ignore non-int fields.
-                    _ => ()
-                }
-            }
-            // 8. Ignore lines that don't have 2 fields.
-            _ => ()
-        }
-    }
-    pairs
-}
-~~~~
-
-This example shows the use of `Option`,
-along with some other forms of error-handling (and non-handling).
-We will look at these mechanisms
-and then modify parts of the example to perform "better" error handling.
-
-# Options
-
-The simplest and most lightweight mechanism in Rust for indicating an error is the type `std::option::Option<T>`.
-This type is a general purpose `enum`
-for conveying a value of type `T`, represented as `Some(T)`
-_or_ the sentinel `None`, to indicate the absence of a `T` value.
-For simple APIs, it may be sufficient to encode errors as `Option<T>`,
-returning `Some(T)` on success and `None` on error.
-In the example program, the call to `from_str::<int>` returns `Option<int>`
-with the understanding that "all parse errors" result in `None`.
-The resulting `Option<int>` values are matched against the pattern `(Some(a), Some(b))`
-in steps 5 and 6 in the example program,
-to handle the case in which both fields were parsed successfully.
-
-Using `Option` as in this API has some advantages:
-
-  - Simple API, users can read it and guess how it works.
-  - Very efficient, only an extra `enum` tag on return values.
-  - Caller has flexibility in handling or propagating errors.
-  - Caller is forced to acknowledge existence of possible-error before using value.
-
-However, it has serious disadvantages too:
-
-  - Verbose, requires matching results or calling `Option::unwrap` everywhere.
-  - Infects caller: if caller doesn't know how to handle the error, must propagate (or force).
-  - Temptation to do just that: force the `Some(T)` case by blindly calling `unwrap`,
-    which hides the error from the API without providing any way to make the program robust against the error.
-  - Collapses all errors into one:
-    - Caller can't handle different errors differently.
-    - Caller can't even report a very precise error message
-
-Note that in order to keep the example code reasonably compact,
-several unwanted cases are silently ignored:
-lines that do not contain two fields, as well as fields that do not parse as ints.
-To propagate these cases to the caller using `Option` would require even more verbose code.
-
-# Results
-
-Before getting into _trapping_ the error,
-we will look at a slight refinement on the `Option` type above.
-This second mechanism for indicating an error is called a `Result`.
-The type `std::result::Result<T,E>` is another simple `enum` type with two forms, `Ok(T)` and `Err(E)`.
-The `Result` type is not substantially different from the `Option` type in terms of its ergonomics.
-Its main advantage is that the error constructor `Err(E)` can convey _more detail_ about the error.
-For example, the `from_str` API could be reformed
-to return a `Result` carrying an informative description of a parse error,
-like this:
-
-~~~~ {.ignore}
-enum IntParseErr {
-     EmptyInput,
-     Overflow,
-     BadChar(char)
-}
-
-fn from_str(&str) -> Result<int,IntParseErr> {
-  // ...
-}
-~~~~
-
-This would give the caller more information for both handling and reporting the error,
-but would otherwise retain the verbosity problems of using `Option`.
-In particular, it would still be necessary for the caller to return a further `Result` to _its_ caller if it did not want to handle the error.
-Manually propagating result values this way can be attractive in certain circumstances
-&mdash; for example when processing must halt on the very first error, or backtrack &mdash;
-but as we will see later, many cases have simpler options available.
-
-# Failure
-
-The third and arguably easiest mechanism for handling errors is called "failure".
-In fact it was hinted at earlier by suggesting that one can choose to propagate `Option` or `Result` types _or "force" them_.
-"Forcing" them, in this case, means calling a method like `Option<T>::unwrap`,
-which contains the following code:
-
-~~~~ {.ignore}
-pub fn unwrap(self) -> T {
-    match self {
-      Some(x) => return x,
-      None => fail!("option::unwrap `None`")
-    }
-}
-~~~~
-
-That is, it returns `T` when `self` is `Some(T)`, and  _fails_ when `self` is `None`.
-
-Every Rust task can _fail_, either indirectly due to a kill signal or other asynchronous event,
-or directly by failing an `assert!` or calling the `fail!` macro.
-Failure is an _unrecoverable event_ at the task level:
-it causes the task to halt normal execution and unwind its control stack,
-freeing all task-local resources (the local heap as well as any task-owned values from the global heap)
-and running destructors (the `drop` method of the `Drop` trait)
-as frames are unwound and heap values destroyed.
-A failing task is not permitted to "catch" the unwinding during failure and recover,
-it is only allowed to clean up and exit.
-
-Failure has advantages:
-
-  - Simple and non-verbose. Suitable for programs that can't reasonably continue past an error anyways.
-  - _All_ errors (except memory-safety errors) can be uniformly trapped in a supervisory task outside the failing task.
-    For a large program to be robust against a variety of errors,
-    often some form of task-level partitioning to contain pervasive errors (arithmetic overflow, division by zero,
-    logic bugs) is necessary anyways.
-
-As well as obvious disadvantages:
-
-  - A blunt instrument, terminates the containing task entirely.
-
-Recall that in the first two approaches to error handling,
-the example program was only handling success cases, and ignoring error cases.
-That is, if the input is changed to contain a malformed line:
-
-~~~~ {.notrust}
-$ cat bad.txt
-1 2
-34 56
-ostrich
-789 123
-45 67
-~~~~
-
-Then the program would give the same output as if there was no error:
-
-~~~~ {.notrust}
-$ ./example bad.txt
-0001, 0002
-0034, 0056
-0789, 0123
-0045, 0067
-~~~~
-
-If the example is rewritten to use failure, these error cases can be trapped.
-In this rewriting, failures are trapped by placing the I/O logic in a sub-task,
-and trapping its exit status using `task::try`:
-
-~~~~
-# #[allow(unused_imports)];
-# extern mod extra;
-use std::io::buffered::BufferedReader;
-use std::io::File;
-use std::task;
-# mod BufferedReader {
-#     use std::io::File;
-#     use std::io::mem::MemReader;
-#     use std::io::buffered::BufferedReader;
-#     static s : &'static [u8] = bytes!("1 2\n\
-#                                        34 56\n\
-#                                        789 123\n\
-#                                        45 67\n\
-#                                        ");
-#     pub fn new(_inner: Option<File>) -> BufferedReader<MemReader> {
-#           BufferedReader::new(MemReader::new(s.to_owned()))
-#     }
-# }
-
-fn main() {
-
-    // Isolate failure within a subtask.
-    let result = do task::try {
-
-        // The protected logic.
-        let pairs = read_int_pairs();
-        for &(a,b) in pairs.iter() {
-            println!("{:4.4d}, {:4.4d}", a, b);
-        }
-
-    };
-    if result.is_err() {
-            println("parsing failed");
-    }
-}
-
-fn read_int_pairs() -> ~[(int,int)] {
-    let mut pairs = ~[];
-#    let _g = std::io::ignore_io_error();
-    let path = Path::new(&"foo.txt");
-
-    let mut reader = BufferedReader::new(File::open(&path));
-    for line in reader.lines() {
-        match line.words().to_owned_vec() {
-            [a, b] => pairs.push((from_str::<int>(a).unwrap(),
-                                  from_str::<int>(b).unwrap())),
-
-            // Explicitly fail on malformed lines.
-            _ => fail!()
-        }
-    }
-    pairs
-}
-~~~~
-
-With these changes in place, running the program on malformed input gives a different answer:
-
-~~~~ {.notrust}
-$ ./example bad.txt
-rust: task failed at 'explicit failure', ./example.rs:44
-parsing failed
-~~~~
-
-Note that while failure unwinds the sub-task performing I/O in `read_int_pairs`,
-control returns to `main` and can easily continue uninterrupted.
-In this case, control simply prints out `parsing failed` and then exits `main` (successfully).
-Failure of a (sub-)task is analogous to calling `exit(1)` or `abort()` in a unix C program:
-all the state of a sub-task is cleanly discarded on exit,
-and a supervisor task can take appropriate action
-without worrying about its own state having been corrupted.
-
-# Conditions
-
-The final mechanism for handling errors is called a "condition".
-Conditions are less blunt than failure, and less cumbersome than the `Option` or `Result` types;
-indeed they are designed to strike just the right balance between the two.
-Conditions require some care to use effectively, but give maximum flexibility with minimum verbosity.
-While conditions use exception-like terminology ("trap", "raise") they are significantly different:
-
-  - Like exceptions and failure, conditions separate the site at which the error is raised from the site where it is trapped.
-  - Unlike exceptions and unlike failure, when a condition is raised and trapped, _no unwinding occurs_.
-  - A successfully trapped condition causes execution to continue _at the site of the error_, as though no error occurred.
-
-Conditions are declared with the `condition!` macro.
-Each condition has a name, an input type and an output type, much like a function.
-In fact, conditions are implemented as dynamically-scoped functions held in task local storage.
-
-The `condition!` macro declares a module with the name of the condition;
-the module contains a single static value called `cond`, of type `std::condition::Condition`.
-The `cond` value within the module is the rendezvous point
-between the site of error and the site that handles the error.
-It has two methods of interest: `raise` and `trap`.
-
-The `raise` method maps a value of the condition's input type to its output type.
-The input type should therefore convey all relevant information to the condition handler.
-The output type should convey all relevant information _for continuing execution at the site of error_.
-When the error site raises a condition handler,
-the `Condition::raise` method searches for the innermost installed task-local condition _handler_,
-and if any such handler is found, calls it with the provided input value.
-If no handler is found, `Condition::raise` will fail the task with an appropriate error message.
-
-Rewriting the example to use a condition in place of ignoring malformed lines makes it slightly longer,
-but similarly clear as the version that used `fail!` in the logic where the error occurs:
-
-~~~~
-# #[allow(unused_imports)];
-# extern mod extra;
-use std::io::buffered::BufferedReader;
-use std::io::File;
-# mod BufferedReader {
-#     use std::io::File;
-#     use std::io::mem::MemReader;
-#     use std::io::buffered::BufferedReader;
-#     static s : &'static [u8] = bytes!("1 2\n\
-#                                        34 56\n\
-#                                        789 123\n\
-#                                        45 67\n\
-#                                        ");
-#     pub fn new(_inner: Option<File>) -> BufferedReader<MemReader> {
-#           BufferedReader::new(MemReader::new(s.to_owned()))
-#     }
-# }
-
-// Introduce a new condition.
-condition! {
-    pub malformed_line : ~str -> (int,int);
-}
-
-fn main() {
-    let pairs = read_int_pairs();
-    for &(a,b) in pairs.iter() {
-        println!("{:4.4d}, {:4.4d}", a, b);
-    }
-}
-
-fn read_int_pairs() -> ~[(int,int)] {
-    let mut pairs = ~[];
-#    let _g = std::io::ignore_io_error();
-    let path = Path::new(&"foo.txt");
-
-    let mut reader = BufferedReader::new(File::open(&path));
-    for line in reader.lines() {
-        match line.words().to_owned_vec() {
-            [a, b] => pairs.push((from_str::<int>(a).unwrap(),
-                                  from_str::<int>(b).unwrap())),
-            // On malformed lines, call the condition handler and
-            // push whatever the condition handler returns.
-            _ => pairs.push(malformed_line::cond.raise(line.clone()))
-        }
-    }
-    pairs
-}
-~~~~
-
-When this is run on malformed input, it still fails,
-but with a slightly different failure message than before:
-
-~~~~ {.notrust}
-$ ./example bad.txt
-rust: task failed at 'Unhandled condition: malformed_line: ~"ostrich"', .../libstd/condition.rs:43
-~~~~
-
-While this superficially resembles the trapped `fail!` call before,
-it is only because the example did not install a handler for the condition.
-The different failure message is indicating, among other things,
-that the condition-handling system is being invoked and failing
-only due to the absence of a _handler_ that traps the condition.
-
-# Trapping a condition
-
-To trap a condition, use `Condition::trap` in some caller of the site that calls `Condition::raise`.
-For example, this version of the program traps the `malformed_line` condition
-and replaces bad input lines with the pair `(-1,-1)`:
-
-~~~~
-# #[allow(unused_imports)];
-# extern mod extra;
-use std::io::buffered::BufferedReader;
-use std::io::File;
-# mod BufferedReader {
-#     use std::io::File;
-#     use std::io::mem::MemReader;
-#     use std::io::buffered::BufferedReader;
-#     static s : &'static [u8] = bytes!("1 2\n\
-#                                        34 56\n\
-#                                        789 123\n\
-#                                        45 67\n\
-#                                        ");
-#     pub fn new(_inner: Option<File>) -> BufferedReader<MemReader> {
-#           BufferedReader::new(MemReader::new(s.to_owned()))
-#     }
-# }
-
-condition! {
-    pub malformed_line : ~str -> (int,int);
-}
-
-fn main() {
-    // Trap the condition:
-    malformed_line::cond.trap(|_| (-1,-1)).inside(|| {
-
-        // The protected logic.
-        let pairs = read_int_pairs();
-        for &(a,b) in pairs.iter() {
-                println!("{:4.4d}, {:4.4d}", a, b);
-        }
-
-    })
-}
-
-fn read_int_pairs() -> ~[(int,int)] {
-    let mut pairs = ~[];
-#    let _g = std::io::ignore_io_error();
-    let path = Path::new(&"foo.txt");
-
-    let mut reader = BufferedReader::new(File::open(&path));
-    for line in reader.lines() {
-        match line.words().to_owned_vec() {
-            [a, b] => pairs.push((from_str::<int>(a).unwrap(),
-                                  from_str::<int>(b).unwrap())),
-            _ => pairs.push(malformed_line::cond.raise(line.clone()))
-        }
-    }
-    pairs
-}
-~~~~
-
-Note that the remainder of the program is _unchanged_ with this trap in place;
-only the caller that installs the trap changed.
-Yet when the condition-trapping variant runs on the malformed input,
-it continues execution past the malformed line, substituting the handler's return value.
-
-~~~~ {.notrust}
-$ ./example bad.txt
-0001, 0002
-0034, 0056
--0001, -0001
-0789, 0123
-0045, 0067
-~~~~
-
-# Refining a condition
-
-As you work with a condition, you may find that the original set of options you present for recovery is insufficient.
-This is no different than any other issue of API design:
-a condition handler is an API for recovering from the condition, and sometimes APIs need to be enriched.
-In the example program, the first form of the `malformed_line` API implicitly assumes that recovery involves a substitute value.
-This assumption may not be correct; some callers may wish to skip malformed lines, for example.
-Changing the condition's return type from `(int,int)` to `Option<(int,int)>` will suffice to support this type of recovery:
-
-~~~~
-# #[allow(unused_imports)];
-# extern mod extra;
-use std::io::buffered::BufferedReader;
-use std::io::File;
-# mod BufferedReader {
-#     use std::io::File;
-#     use std::io::mem::MemReader;
-#     use std::io::buffered::BufferedReader;
-#     static s : &'static [u8] = bytes!("1 2\n\
-#                                        34 56\n\
-#                                        789 123\n\
-#                                        45 67\n\
-#                                        ");
-#     pub fn new(_inner: Option<File>) -> BufferedReader<MemReader> {
-#           BufferedReader::new(MemReader::new(s.to_owned()))
-#     }
-# }
-
-// Modify the condition signature to return an Option.
-condition! {
-    pub malformed_line : ~str -> Option<(int,int)>;
-}
-
-fn main() {
-    // Trap the condition and return `None`
-    malformed_line::cond.trap(|_| None).inside(|| {
-
-        // The protected logic.
-        let pairs = read_int_pairs();
-        for &(a,b) in pairs.iter() {
-            println!("{:4.4d}, {:4.4d}", a, b);
-        }
-
-    })
-}
-
-fn read_int_pairs() -> ~[(int,int)] {
-    let mut pairs = ~[];
-#    let _g = std::io::ignore_io_error();
-    let path = Path::new(&"foo.txt");
-
-    let mut reader = BufferedReader::new(File::open(&path));
-    for line in reader.lines() {
-        match line.words().to_owned_vec() {
-            [a, b] => pairs.push((from_str::<int>(a).unwrap(),
-                                  from_str::<int>(b).unwrap())),
-
-            // On malformed lines, call the condition handler and
-            // either ignore the line (if the handler returns `None`)
-            // or push any `Some(pair)` value returned instead.
-            _ => {
-                match malformed_line::cond.raise(line.clone()) {
-                    Some(pair) => pairs.push(pair),
-                    None => ()
-                }
-            }
-        }
-    }
-    pairs
-}
-~~~~
-
-Again, note that the remainder of the program is _unchanged_,
-in particular the signature of `read_int_pairs` is unchanged,
-even though the innermost part of its reading-loop has a new way of handling a malformed line.
-When the example is run with the `None` trap in place,
-the line is ignored as it was in the first example,
-but the choice of whether to ignore or use a substitute value has been moved to some caller,
-possibly a distant caller.
-
-~~~~ {.notrust}
-$ ./example bad.txt
-0001, 0002
-0034, 0056
-0789, 0123
-0045, 0067
-~~~~
-
-# Further refining a condition
-
-Like with any API, the process of refining argument and return types of a condition will continue,
-until all relevant combinations encountered in practice are encoded.
-In the example, suppose a third possible recovery form arose: reusing the previous value read.
-This can be encoded in the handler API by introducing a helper type: `enum MalformedLineFix`.
-
-~~~~
-# #[allow(unused_imports)];
-# extern mod extra;
-use std::io::buffered::BufferedReader;
-use std::io::File;
-# mod BufferedReader {
-#     use std::io::File;
-#     use std::io::mem::MemReader;
-#     use std::io::buffered::BufferedReader;
-#     static s : &'static [u8] = bytes!("1 2\n\
-#                                        34 56\n\
-#                                        789 123\n\
-#                                        45 67\n\
-#                                        ");
-#     pub fn new(_inner: Option<File>) -> BufferedReader<MemReader> {
-#           BufferedReader::new(MemReader::new(s.to_owned()))
-#     }
-# }
-
-// Introduce a new enum to convey condition-handling strategy to error site.
-pub enum MalformedLineFix {
-     UsePair(int,int),
-     IgnoreLine,
-     UsePreviousLine
-}
-
-// Modify the condition signature to return the new enum.
-// Note: a condition introduces a new module, so the enum must be
-// named with the `super::` prefix to access it.
-condition! {
-    pub malformed_line : ~str -> super::MalformedLineFix;
-}
-
-fn main() {
-    // Trap the condition and return `UsePreviousLine`
-    malformed_line::cond.trap(|_| UsePreviousLine).inside(|| {
-
-        // The protected logic.
-        let pairs = read_int_pairs();
-        for &(a,b) in pairs.iter() {
-            println!("{:4.4d}, {:4.4d}", a, b);
-        }
-
-    })
-}
-
-fn read_int_pairs() -> ~[(int,int)] {
-    let mut pairs = ~[];
-#    let _g = std::io::ignore_io_error();
-    let path = Path::new(&"foo.txt");
-
-    let mut reader = BufferedReader::new(File::open(&path));
-    for line in reader.lines() {
-        match line.words().to_owned_vec() {
-            [a, b] => pairs.push((from_str::<int>(a).unwrap(),
-                                  from_str::<int>(b).unwrap())),
-
-            // On malformed lines, call the condition handler and
-            // take action appropriate to the enum value returned.
-            _ => {
-                match malformed_line::cond.raise(line.clone()) {
-                    UsePair(a,b) => pairs.push((a,b)),
-                    IgnoreLine => (),
-                    UsePreviousLine => {
-                        let prev = pairs[pairs.len() - 1];
-                        pairs.push(prev)
-                    }
-                }
-            }
-        }
-    }
-    pairs
-}
-~~~~
-
-Running the example with `UsePreviousLine` as the fix code returned from the handler
-gives the expected result:
-
-~~~~ {.notrust}
-$ ./example bad.txt
-0001, 0002
-0034, 0056
-0034, 0056
-0789, 0123
-0045, 0067
-~~~~
-
-At this point the example has a rich variety of recovery options,
-none of which is visible to casual users of the `read_int_pairs` function.
-This is intentional: part of the purpose of using a condition
-is to free intermediate callers from the burden of having to write repetitive error-propagation logic,
-and/or having to change function call and return types as error-handling strategies are refined.
-
-# Multiple conditions, intermediate callers
-
-So far the function trapping the condition and the function raising it have been immediately adjacent in the call stack.
-That is, the caller traps and its immediate callee raises.
-In most programs, the function that traps may be separated by very many function calls from the function that raises.
-Again, this is part of the point of using conditions:
-to support that separation without having to thread multiple error values and recovery strategies all the way through the program's main logic.
-
-Careful readers will notice that there is a remaining failure mode in the example program: the call to `.unwrap()` when parsing each integer.
-For example, when presented with a file that has the correct number of fields on a line,
-but a non-numeric value in one of them, such as this:
-
-~~~~ {.notrust}
-$ cat bad.txt
-1 2
-34 56
-7 marmot
-789 123
-45 67
-~~~~
-
-
-Then the program fails once more:
-
-~~~~ {.notrust}
-$ ./example bad.txt
-task <unnamed> failed at 'called `Option::unwrap()` on a `None` value', .../libstd/option.rs:314
-~~~~
-
-To make the program robust &mdash; or at least flexible &mdash; in the face of this potential failure,
-a second condition and a helper function will suffice:
-
-~~~~
-# #[allow(unused_imports)];
-# extern mod extra;
-use std::io::buffered::BufferedReader;
-use std::io::File;
-# mod BufferedReader {
-#     use std::io::File;
-#     use std::io::mem::MemReader;
-#     use std::io::buffered::BufferedReader;
-#     static s : &'static [u8] = bytes!("1 2\n\
-#                                        34 56\n\
-#                                        789 123\n\
-#                                        45 67\n\
-#                                        ");
-#     pub fn new(_inner: Option<File>) -> BufferedReader<MemReader> {
-#           BufferedReader::new(MemReader::new(s.to_owned()))
-#     }
-# }
-
-pub enum MalformedLineFix {
-     UsePair(int,int),
-     IgnoreLine,
-     UsePreviousLine
-}
-
-condition! {
-    pub malformed_line : ~str -> ::MalformedLineFix;
-}
-
-// Introduce a second condition.
-condition! {
-    pub malformed_int : ~str -> int;
-}
-
-fn main() {
-    // Trap the `malformed_int` condition and return -1
-    malformed_int::cond.trap(|_| -1).inside(|| {
-
-        // Trap the `malformed_line` condition and return `UsePreviousLine`
-        malformed_line::cond.trap(|_| UsePreviousLine).inside(|| {
-
-            // The protected logic.
-            let pairs = read_int_pairs();
-            for &(a,b) in pairs.iter() {
-                println!("{:4.4d}, {:4.4d}", a, b);
-            }
-
-        })
-    })
-}
-
-// Parse an int; if parsing fails, call the condition handler and
-// return whatever it returns.
-fn parse_int(x: &str) -> int {
-    match from_str::<int>(x) {
-        Some(v) => v,
-        None => malformed_int::cond.raise(x.to_owned())
-    }
-}
-
-fn read_int_pairs() -> ~[(int,int)] {
-    let mut pairs = ~[];
-#    let _g = std::io::ignore_io_error();
-    let path = Path::new(&"foo.txt");
-
-    let mut reader = BufferedReader::new(File::open(&path));
-    for line in reader.lines() {
-        match line.words().to_owned_vec() {
-            // Delegate parsing ints to helper function that will
-            // handle parse errors by calling `malformed_int`.
-            [a, b] => pairs.push((parse_int(a), parse_int(b))),
-
-            _ => {
-                match malformed_line::cond.raise(line.clone()) {
-                    UsePair(a,b) => pairs.push((a,b)),
-                    IgnoreLine => (),
-                    UsePreviousLine => {
-                        let prev = pairs[pairs.len() - 1];
-                        pairs.push(prev)
-                    }
-                }
-            }
-        }
-    }
-    pairs
-}
-~~~~
-
-Again, note that `read_int_pairs` has not changed signature,
-nor has any of the machinery for trapping or raising `malformed_line`,
-but now the program can handle the "right number of fields, non-integral field" form of bad input:
-
-~~~~ {.notrust}
-$ ./example bad.txt
-0001, 0002
-0034, 0056
-0007, -0001
-0789, 0123
-0045, 0067
-~~~~
-
-There are three other things to note in this variant of the example program:
-
-  - It traps multiple conditions simultaneously,
-    nesting the protected logic of one `trap` call inside the other.
-
-  - There is a function in between the `trap` site and `raise` site for the `malformed_int` condition.
-    There could be any number of calls between them:
-    so long as the `raise` occurs within a callee (of any depth) of the logic protected by the `trap` call,
-    it will invoke the handler.
-
-  - This variant insulates callers from a design choice in the library:
-    the `from_str` function was designed to return an `Option<int>`,
-    but this program insulates callers from that choice,
-    routing all `None` values that arise from parsing integers in this file into the condition.
-
-
-# When to use which technique
-
-This tutorial explored several techniques for handling errors.
-Each is appropriate to different circumstances:
-
-  - If an error may be extremely frequent, expected, and very likely dealt with by an immediate caller,
-    then returning an `Option` or `Result` type is best. These types force the caller to handle the error,
-    and incur the lowest speed overhead, usually only returning one extra word to tag the return value.
-    Between `Option` and `Result`: use an `Option` when there is only one kind of error,
-    otherwise make an `enum FooErr` to represent the possible error codes and use `Result<T,FooErr>`.
-
-  - If an error can reasonably be handled at the site it occurs by one of a few strategies &mdash; possibly including failure &mdash;
-    and it is not clear which strategy a caller would want to use, a condition is best.
-    For many errors, the only reasonable "non-stop" recovery strategies are to retry some number of times,
-    create or substitute an empty or sentinel value, ignore the error, or fail.
-
-  - If an error cannot reasonably be handled at the site it occurs,
-    and the only reasonable response is to abandon a large set of operations in progress,
-    then directly failing is best.
-
-Note that an unhandled condition will cause failure (along with a more-informative-than-usual message),
-so if there is any possibility that a caller might wish to "ignore and keep going",
-it is usually harmless to use a condition in place of a direct call to `fail!()`.
-
-
-[^why-no-exceptions]: Exceptions in languages like C++ and Java permit unwinding, like Rust's failure system,
-but with the option to halt unwinding partway through the process and continue execution.
-This behavior unfortunately means that the _heap_ may be left in an inconsistent but accessible state,
-if an exception is thrown part way through the process of initializing or modifying memory.
-To compensate for this risk, correct C++ and Java code must program in an extremely elaborate and difficult "exception-safe" style
-&mdash; effectively transactional style against heap structures &mdash;
-or else risk introducing silent and very difficult-to-debug errors due to control resuming in a corrupted heap after a caught exception.
-These errors are frequently memory-safety errors, which Rust strives to eliminate,
-and so Rust unwinding is unrecoverable within a single task:
-once unwinding starts, the entire local heap of a task is destroyed and the task is terminated.
diff --git a/doc/tutorial-container.md b/doc/tutorial-container.md
deleted file mode 100644 (file)
index 65f536f..0000000
+++ /dev/null
@@ -1,410 +0,0 @@
-% Containers and iterators
-
-# Containers
-
-The container traits are defined in the `std::container` module.
-
-## Unique vectors
-
-Vectors have `O(1)` indexing, push (to the end) and pop (from the end). Vectors
-are the most common container in Rust, and are flexible enough to fit many use
-cases.
-
-Vectors can also be sorted and used as efficient lookup tables with the
-`bsearch()` method, if all the elements are inserted at one time and
-deletions are unnecessary.
-
-## Maps and sets
-
-Maps are collections of unique keys with corresponding values, and sets are
-just unique keys without a corresponding value. The `Map` and `Set` traits in
-`std::container` define the basic interface.
-
-The standard library provides three owned map/set types:
-
-* `std::hashmap::HashMap` and `std::hashmap::HashSet`, requiring the keys to
-  implement `Eq` and `Hash`
-* `std::trie::TrieMap` and `std::trie::TrieSet`, requiring the keys to be `uint`
-* `extra::treemap::TreeMap` and `extra::treemap::TreeSet`, requiring the keys
-  to implement `TotalOrd`
-
-These maps do not use managed pointers so they can be sent between tasks as
-long as the key and value types are sendable. Neither the key or value type has
-to be copyable.
-
-The `TrieMap` and `TreeMap` maps are ordered, while `HashMap` uses an arbitrary
-order.
-
-Each `HashMap` instance has a random 128-bit key to use with a keyed hash,
-making the order of a set of keys in a given hash table randomized. Rust
-provides a [SipHash](https://131002.net/siphash/) implementation for any type
-implementing the `IterBytes` trait.
-
-## Double-ended queues
-
-The `extra::ringbuf` module implements a double-ended queue with `O(1)`
-amortized inserts and removals from both ends of the container. It also has
-`O(1)` indexing like a vector. The contained elements are not required to be
-copyable, and the queue will be sendable if the contained type is sendable.
-Its interface `Deque` is defined in `extra::collections`.
-
-The `extra::dlist` module implements a double-ended linked list, also
-implementing the `Deque` trait, with `O(1)` removals and inserts at either end,
-and `O(1)` concatenation.
-
-## Priority queues
-
-The `extra::priority_queue` module implements a queue ordered by a key.  The
-contained elements are not required to be copyable, and the queue will be
-sendable if the contained type is sendable.
-
-Insertions have `O(log n)` time complexity and checking or popping the largest
-element is `O(1)`. Converting a vector to a priority queue can be done
-in-place, and has `O(n)` complexity. A priority queue can also be converted to
-a sorted vector in-place, allowing it to be used for an `O(n log n)` in-place
-heapsort.
-
-# Iterators
-
-## Iteration protocol
-
-The iteration protocol is defined by the `Iterator` trait in the
-`std::iter` module. The minimal implementation of the trait is a `next`
-method, yielding the next element from an iterator object:
-
-~~~
-/// An infinite stream of zeroes
-struct ZeroStream;
-
-impl Iterator<int> for ZeroStream {
-    fn next(&mut self) -> Option<int> {
-        Some(0)
-    }
-}
-~~~~
-
-Reaching the end of the iterator is signalled by returning `None` instead of
-`Some(item)`:
-
-~~~
-# fn main() {}
-/// A stream of N zeroes
-struct ZeroStream {
-    priv remaining: uint
-}
-
-impl ZeroStream {
-    fn new(n: uint) -> ZeroStream {
-        ZeroStream { remaining: n }
-    }
-}
-
-impl Iterator<int> for ZeroStream {
-    fn next(&mut self) -> Option<int> {
-        if self.remaining == 0 {
-            None
-        } else {
-            self.remaining -= 1;
-            Some(0)
-        }
-    }
-}
-~~~
-
-In general, you cannot rely on the behavior of the `next()` method after it has
-returned `None`. Some iterators may return `None` forever. Others may behave
-differently.
-
-## Container iterators
-
-Containers implement iteration over the contained elements by returning an
-iterator object. For example, vector slices several iterators available:
-
-* `iter()` and `rev_iter()`, for immutable references to the elements
-* `mut_iter()` and `mut_rev_iter()`, for mutable references to the elements
-* `move_iter()` and `move_rev_iter()`, to move the elements out by-value
-
-A typical mutable container will implement at least `iter()`, `mut_iter()` and
-`move_iter()` along with the reverse variants if it maintains an order.
-
-### Freezing
-
-Unlike most other languages with external iterators, Rust has no *iterator
-invalidation*. As long an iterator is still in scope, the compiler will prevent
-modification of the container through another handle.
-
-~~~
-let mut xs = [1, 2, 3];
-{
-    let _it = xs.iter();
-
-    // the vector is frozen for this scope, the compiler will statically
-    // prevent modification
-}
-// the vector becomes unfrozen again at the end of the scope
-~~~
-
-These semantics are due to most container iterators being implemented with `&`
-and `&mut`.
-
-## Iterator adaptors
-
-The `Iterator` trait provides many common algorithms as default methods. For
-example, the `fold` method will accumulate the items yielded by an `Iterator`
-into a single value:
-
-~~~
-let xs = [1, 9, 2, 3, 14, 12];
-let result = xs.iter().fold(0, |accumulator, item| accumulator - *item);
-assert_eq!(result, -41);
-~~~
-
-Most adaptors return an adaptor object implementing the `Iterator` trait itself:
-
-~~~
-let xs = [1, 9, 2, 3, 14, 12];
-let ys = [5, 2, 1, 8];
-let sum = xs.iter().chain(ys.iter()).fold(0, |a, b| a + *b);
-assert_eq!(sum, 57);
-~~~
-
-Some iterator adaptors may return `None` before exhausting the underlying
-iterator. Additionally, if these iterator adaptors are called again after
-returning `None`, they may call their underlying iterator again even if the
-adaptor will continue to return `None` forever. This may not be desired if the
-underlying iterator has side-effects.
-
-In order to provide a guarantee about behavior once `None` has been returned, an
-iterator adaptor named `fuse()` is provided. This returns an iterator that will
-never call its underlying iterator again once `None` has been returned:
-
-~~~
-let xs = [1,2,3,4,5];
-let mut calls = 0;
-let it = xs.iter().scan((), |_, x| {
-    calls += 1;
-    if *x < 3 { Some(x) } else { None }});
-// the iterator will only yield 1 and 2 before returning None
-// If we were to call it 5 times, calls would end up as 5, despite only 2 values
-// being yielded (and therefore 3 unique calls being made). The fuse() adaptor
-// can fix this.
-let mut it = it.fuse();
-it.next();
-it.next();
-it.next();
-it.next();
-it.next();
-assert_eq!(calls, 3);
-~~~
-
-## For loops
-
-The function `range` (or `range_inclusive`) allows to simply iterate through a given range:
-
-~~~
-for i in range(0, 5) {
-  print!("{} ", i) // prints "0 1 2 3 4"
-}
-
-for i in std::iter::range_inclusive(0, 5) { // needs explicit import
-  print!("{} ", i) // prints "0 1 2 3 4 5"
-}
-~~~
-
-The `for` keyword can be used as sugar for iterating through any iterator:
-
-~~~
-let xs = [2u, 3, 5, 7, 11, 13, 17];
-
-// print out all the elements in the vector
-for x in xs.iter() {
-    println(x.to_str())
-}
-
-// print out all but the first 3 elements in the vector
-for x in xs.iter().skip(3) {
-    println(x.to_str())
-}
-~~~
-
-For loops are *often* used with a temporary iterator object, as above. They can
-also advance the state of an iterator in a mutable location:
-
-~~~
-let xs = [1, 2, 3, 4, 5];
-let ys = ["foo", "bar", "baz", "foobar"];
-
-// create an iterator yielding tuples of elements from both vectors
-let mut it = xs.iter().zip(ys.iter());
-
-// print out the pairs of elements up to (&3, &"baz")
-for (x, y) in it {
-    println!("{} {}", *x, *y);
-
-    if *x == 3 {
-        break;
-    }
-}
-
-// yield and print the last pair from the iterator
-println!("last: {:?}", it.next());
-
-// the iterator is now fully consumed
-assert!(it.next().is_none());
-~~~
-
-## Conversion
-
-Iterators offer generic conversion to containers with the `collect` adaptor:
-
-~~~
-let xs = [0, 1, 1, 2, 3, 5, 8];
-let ys = xs.rev_iter().skip(1).map(|&x| x * 2).collect::<~[int]>();
-assert_eq!(ys, ~[10, 6, 4, 2, 2, 0]);
-~~~
-
-The method requires a type hint for the container type, if the surrounding code
-does not provide sufficient information.
-
-Containers can provide conversion from iterators through `collect` by
-implementing the `FromIterator` trait. For example, the implementation for
-vectors is as follows:
-
-~~~ {.xfail-test}
-impl<A> FromIterator<A> for ~[A] {
-    pub fn from_iterator<T: Iterator<A>>(iterator: &mut T) -> ~[A] {
-        let (lower, _) = iterator.size_hint();
-        let mut xs = with_capacity(lower);
-        for x in iterator {
-            xs.push(x);
-        }
-        xs
-    }
-}
-~~~
-
-### Size hints
-
-The `Iterator` trait provides a `size_hint` default method, returning a lower
-bound and optionally on upper bound on the length of the iterator:
-
-~~~ {.xfail-test}
-fn size_hint(&self) -> (uint, Option<uint>) { (0, None) }
-~~~
-
-The vector implementation of `FromIterator` from above uses the lower bound
-to pre-allocate enough space to hold the minimum number of elements the
-iterator will yield.
-
-The default implementation is always correct, but it should be overridden if
-the iterator can provide better information.
-
-The `ZeroStream` from earlier can provide an exact lower and upper bound:
-
-~~~
-# fn main() {}
-/// A stream of N zeroes
-struct ZeroStream {
-    priv remaining: uint
-}
-
-impl ZeroStream {
-    fn new(n: uint) -> ZeroStream {
-        ZeroStream { remaining: n }
-    }
-
-    fn size_hint(&self) -> (uint, Option<uint>) {
-        (self.remaining, Some(self.remaining))
-    }
-}
-
-impl Iterator<int> for ZeroStream {
-    fn next(&mut self) -> Option<int> {
-        if self.remaining == 0 {
-            None
-        } else {
-            self.remaining -= 1;
-            Some(0)
-        }
-    }
-}
-~~~
-
-## Double-ended iterators
-
-The `DoubleEndedIterator` trait represents an iterator able to yield elements
-from either end of a range. It inherits from the `Iterator` trait and extends
-it with the `next_back` function.
-
-A `DoubleEndedIterator` can be flipped with the `invert` adaptor, returning
-another `DoubleEndedIterator` with `next` and `next_back` exchanged.
-
-~~~
-let xs = [1, 2, 3, 4, 5, 6];
-let mut it = xs.iter();
-println!("{:?}", it.next()); // prints `Some(&1)`
-println!("{:?}", it.next()); // prints `Some(&2)`
-println!("{:?}", it.next_back()); // prints `Some(&6)`
-
-// prints `5`, `4` and `3`
-for &x in it.invert() {
-    println!("{}", x)
-}
-~~~
-
-The `rev_iter` and `mut_rev_iter` methods on vectors just return an inverted
-version of the standard immutable and mutable vector iterators.
-
-The `chain`, `map`, `filter`, `filter_map` and `inspect` adaptors are
-`DoubleEndedIterator` implementations if the underlying iterators are.
-
-~~~
-let xs = [1, 2, 3, 4];
-let ys = [5, 6, 7, 8];
-let mut it = xs.iter().chain(ys.iter()).map(|&x| x * 2);
-
-println!("{:?}", it.next()); // prints `Some(2)`
-
-// prints `16`, `14`, `12`, `10`, `8`, `6`, `4`
-for x in it.invert() {
-    println!("{}", x);
-}
-~~~
-
-The `reverse_` method is also available for any double-ended iterator yielding
-mutable references. It can be used to reverse a container in-place. Note that
-the trailing underscore is a workaround for issue #5898 and will be removed.
-
-~~~
-let mut ys = [1, 2, 3, 4, 5];
-ys.mut_iter().reverse_();
-assert_eq!(ys, [5, 4, 3, 2, 1]);
-~~~
-
-## Random-access iterators
-
-The `RandomAccessIterator` trait represents an iterator offering random access
-to the whole range. The `indexable` method retrieves the number of elements
-accessible with the `idx` method.
-
-The `chain` adaptor is an implementation of `RandomAccessIterator` if the
-underlying iterators are.
-
-~~~
-let xs = [1, 2, 3, 4, 5];
-let ys = ~[7, 9, 11];
-let mut it = xs.iter().chain(ys.iter());
-println!("{:?}", it.idx(0)); // prints `Some(&1)`
-println!("{:?}", it.idx(5)); // prints `Some(&7)`
-println!("{:?}", it.idx(7)); // prints `Some(&11)`
-println!("{:?}", it.idx(8)); // prints `None`
-
-// yield two elements from the beginning, and one from the end
-it.next();
-it.next();
-it.next_back();
-
-println!("{:?}", it.idx(0)); // prints `Some(&3)`
-println!("{:?}", it.idx(4)); // prints `Some(&9)`
-println!("{:?}", it.idx(6)); // prints `None`
-~~~
diff --git a/doc/tutorial-ffi.md b/doc/tutorial-ffi.md
deleted file mode 100644 (file)
index 39eff68..0000000
+++ /dev/null
@@ -1,430 +0,0 @@
-% Rust Foreign Function Interface Tutorial
-
-# Introduction
-
-This tutorial will use the [snappy](https://code.google.com/p/snappy/)
-compression/decompression library as an introduction to writing bindings for
-foreign code. Rust is currently unable to call directly into a C++ library, but
-snappy includes a C interface (documented in
-[`snappy-c.h`](https://code.google.com/p/snappy/source/browse/trunk/snappy-c.h)).
-
-The following is a minimal example of calling a foreign function which will
-compile if snappy is installed:
-
-~~~~ {.xfail-test}
-use std::libc::size_t;
-
-#[link(name = "snappy")]
-extern {
-    fn snappy_max_compressed_length(source_length: size_t) -> size_t;
-}
-
-fn main() {
-    let x = unsafe { snappy_max_compressed_length(100) };
-    println!("max compressed length of a 100 byte buffer: {}", x);
-}
-~~~~
-
-The `extern` block is a list of function signatures in a foreign library, in
-this case with the platform's C ABI. The `#[link(...)]` attribute is used to
-instruct the linker to link against the snappy library so the symbols are
-resolved.
-
-Foreign functions are assumed to be unsafe so calls to them need to be wrapped
-with `unsafe {}` as a promise to the compiler that everything contained within
-truly is safe. C libraries often expose interfaces that aren't thread-safe, and
-almost any function that takes a pointer argument isn't valid for all possible
-inputs since the pointer could be dangling, and raw pointers fall outside of
-Rust's safe memory model.
-
-When declaring the argument types to a foreign function, the Rust compiler can
-not check if the declaration is correct, so specifying it correctly is part of
-keeping the binding correct at runtime.
-
-The `extern` block can be extended to cover the entire snappy API:
-
-~~~~ {.xfail-test}
-use std::libc::{c_int, size_t};
-
-#[link(name = "snappy")]
-extern {
-    fn snappy_compress(input: *u8,
-                       input_length: size_t,
-                       compressed: *mut u8,
-                       compressed_length: *mut size_t) -> c_int;
-    fn snappy_uncompress(compressed: *u8,
-                         compressed_length: size_t,
-                         uncompressed: *mut u8,
-                         uncompressed_length: *mut size_t) -> c_int;
-    fn snappy_max_compressed_length(source_length: size_t) -> size_t;
-    fn snappy_uncompressed_length(compressed: *u8,
-                                  compressed_length: size_t,
-                                  result: *mut size_t) -> c_int;
-    fn snappy_validate_compressed_buffer(compressed: *u8,
-                                         compressed_length: size_t) -> c_int;
-}
-~~~~
-
-# Creating a safe interface
-
-The raw C API needs to be wrapped to provide memory safety and make use of higher-level concepts
-like vectors. A library can choose to expose only the safe, high-level interface and hide the unsafe
-internal details.
-
-Wrapping the functions which expect buffers involves using the `vec::raw` module to manipulate Rust
-vectors as pointers to memory. Rust's vectors are guaranteed to be a contiguous block of memory. The
-length is number of elements currently contained, and the capacity is the total size in elements of
-the allocated memory. The length is less than or equal to the capacity.
-
-~~~~ {.xfail-test}
-pub fn validate_compressed_buffer(src: &[u8]) -> bool {
-    unsafe {
-        snappy_validate_compressed_buffer(src.as_ptr(), src.len() as size_t) == 0
-    }
-}
-~~~~
-
-The `validate_compressed_buffer` wrapper above makes use of an `unsafe` block, but it makes the
-guarantee that calling it is safe for all inputs by leaving off `unsafe` from the function
-signature.
-
-The `snappy_compress` and `snappy_uncompress` functions are more complex, since a buffer has to be
-allocated to hold the output too.
-
-The `snappy_max_compressed_length` function can be used to allocate a vector with the maximum
-required capacity to hold the compressed output. The vector can then be passed to the
-`snappy_compress` function as an output parameter. An output parameter is also passed to retrieve
-the true length after compression for setting the length.
-
-~~~~ {.xfail-test}
-pub fn compress(src: &[u8]) -> ~[u8] {
-    unsafe {
-        let srclen = src.len() as size_t;
-        let psrc = src.as_ptr();
-
-        let mut dstlen = snappy_max_compressed_length(srclen);
-        let mut dst = vec::with_capacity(dstlen as uint);
-        let pdst = dst.as_mut_ptr();
-
-        snappy_compress(psrc, srclen, pdst, &mut dstlen);
-        dst.set_len(dstlen as uint);
-        dst
-    }
-}
-~~~~
-
-Decompression is similar, because snappy stores the uncompressed size as part of the compression
-format and `snappy_uncompressed_length` will retrieve the exact buffer size required.
-
-~~~~ {.xfail-test}
-pub fn uncompress(src: &[u8]) -> Option<~[u8]> {
-    unsafe {
-        let srclen = src.len() as size_t;
-        let psrc = src.as_ptr();
-
-        let mut dstlen: size_t = 0;
-        snappy_uncompressed_length(psrc, srclen, &mut dstlen);
-
-        let mut dst = vec::with_capacity(dstlen as uint);
-        let pdst = dst.as_mut_ptr();
-
-        if snappy_uncompress(psrc, srclen, pdst, &mut dstlen) == 0 {
-            dst.set_len(dstlen as uint);
-            Some(dst)
-        } else {
-            None // SNAPPY_INVALID_INPUT
-        }
-    }
-}
-~~~~
-
-For reference, the examples used here are also available as an [library on
-GitHub](https://github.com/thestinger/rust-snappy).
-
-# Stack management
-
-Rust tasks by default run on a "large stack". This is actually implemented as a
-reserving a large segment of the address space and then lazily mapping in pages
-as they are needed. When calling an external C function, the code is invoked on
-the same stack as the rust stack. This means that there is no extra
-stack-switching mechanism in place because it is assumed that the large stack
-for the rust task is plenty for the C function to have.
-
-A planned future improvement (net yet implemented at the time of this writing)
-is to have a guard page at the end of every rust stack. No rust function will
-hit this guard page (due to Rust's usage of LLVM's `__morestack`). The intention
-for this unmapped page is to prevent infinite recursion in C from overflowing
-onto other rust stacks. If the guard page is hit, then the process will be
-terminated with a message saying that the guard page was hit.
-
-For normal external function usage, this all means that there shouldn't be any
-need for any extra effort on a user's perspective. The C stack naturally
-interleaves with the rust stack, and it's "large enough" for both to
-interoperate. If, however, it is determined that a larger stack is necessary,
-there are appropriate functions in the task spawning API to control the size of
-the stack of the task which is spawned.
-
-# Destructors
-
-Foreign libraries often hand off ownership of resources to the calling code.
-When this occurs, we must use Rust's destructors to provide safety and guarantee
-the release of these resources (especially in the case of failure).
-
-As an example, we give a reimplementation of owned boxes by wrapping `malloc`
-and `free`:
-
-~~~~
-use std::cast;
-use std::libc::{c_void, size_t, malloc, free};
-use std::ptr;
-use std::unstable::intrinsics;
-
-// Define a wrapper around the handle returned by the foreign code.
-// Unique<T> has the same semantics as ~T
-pub struct Unique<T> {
-    // It contains a single raw, mutable pointer to the object in question.
-    priv ptr: *mut T
-}
-
-// Implement methods for creating and using the values in the box.
-// NB: For simplicity and correctness, we require that T has kind Send
-// (owned boxes relax this restriction, and can contain managed (GC) boxes).
-// This is because, as implemented, the garbage collector would not know
-// about any shared boxes stored in the malloc'd region of memory.
-impl<T: Send> Unique<T> {
-    pub fn new(value: T) -> Unique<T> {
-        unsafe {
-            let ptr = malloc(std::mem::size_of::<T>() as size_t) as *mut T;
-            assert!(!ptr::is_null(ptr));
-            // `*ptr` is uninitialized, and `*ptr = value` would attempt to destroy it
-            // move_val_init moves a value into this memory without
-            // attempting to drop the original value.
-            intrinsics::move_val_init(&mut *ptr, value);
-            Unique{ptr: ptr}
-        }
-    }
-
-    // the 'r lifetime results in the same semantics as `&*x` with ~T
-    pub fn borrow<'r>(&'r self) -> &'r T {
-        unsafe { cast::copy_lifetime(self, &*self.ptr) }
-    }
-
-    // the 'r lifetime results in the same semantics as `&mut *x` with ~T
-    pub fn borrow_mut<'r>(&'r mut self) -> &'r mut T {
-        unsafe { cast::copy_mut_lifetime(self, &mut *self.ptr) }
-    }
-}
-
-// The key ingredient for safety, we associate a destructor with
-// Unique<T>, making the struct manage the raw pointer: when the
-// struct goes out of scope, it will automatically free the raw pointer.
-// NB: This is an unsafe destructor, because rustc will not normally
-// allow destructors to be associated with parametrized types, due to
-// bad interaction with managed boxes. (With the Send restriction,
-// we don't have this problem.)
-#[unsafe_destructor]
-impl<T: Send> Drop for Unique<T> {
-    fn drop(&mut self) {
-        unsafe {
-            let x = intrinsics::uninit(); // dummy value to swap in
-            // We need to move the object out of the box, so that
-            // the destructor is called (at the end of this scope.)
-            ptr::replace_ptr(self.ptr, x);
-            free(self.ptr as *c_void)
-        }
-    }
-}
-
-// A comparison between the built-in ~ and this reimplementation
-fn main() {
-    {
-        let mut x = ~5;
-        *x = 10;
-    } // `x` is freed here
-
-    {
-        let mut y = Unique::new(5);
-        *y.borrow_mut() = 10;
-    } // `y` is freed here
-}
-~~~~
-
-# Linking
-
-The `link` attribute on `extern` blocks provides the basic building block for
-instructing rustc how it will link to native libraries. There are two accepted
-forms of the link attribute today:
-
-* `#[link(name = "foo")]`
-* `#[link(name = "foo", kind = "bar")]`
-
-In both of these cases, `foo` is the name of the native library that we're
-linking to, and in the second case `bar` is the type of native library that the
-compiler is linking to. There are currently three known types of native
-libraries:
-
-* Dynamic - `#[link(name = "readline")]
-* Static - `#[link(name = "my_build_dependency", kind = "static")]
-* Frameworks - `#[link(name = "CoreFoundation", kind = "framework")]
-
-Note that frameworks are only available on OSX targets.
-
-The different `kind` values are meant to differentiate how the native library
-participates in linkage. From a linkage perspective, the rust compiler creates
-two flavors of artifacts: partial (rlib/staticlib) and final (dylib/binary).
-Native dynamic libraries and frameworks are propagated to the final artifact
-boundary, while static libraries are not propagated at all.
-
-A few examples of how this model can be used are:
-
-* A native build dependency. Sometimes some C/C++ glue is needed when writing
-  some rust code, but distribution of the C/C++ code in a library format is just
-  a burden. In this case, the code will be archived into `libfoo.a` and then the
-  rust crate would declare a dependency via `#[link(name = "foo", kind =
-  "static")]`.
-
-  Regardless of the flavor of output for the crate, the native static library
-  will be included in the output, meaning that distribution of the native static
-  library is not necessary.
-
-* A normal dynamic dependency. Common system libraries (like `readline`) are
-  available on a large number of systems, and often a static copy of these
-  libraries cannot be found. When this dependency is included in a rust crate,
-  partial targets (like rlibs) will not link to the library, but when the rlib
-  is included in a final target (like a binary), the native library will be
-  linked in.
-
-On OSX, frameworks behave with the same semantics as a dynamic library.
-
-## The `link_args` attribute
-
-There is one other way to tell rustc how to customize linking, and that is via
-the `link_args` attribute. This attribute is applied to `extern` blocks and
-specifies raw flags which need to get passed to the linker when producing an
-artifact. An example usage would be:
-
-~~~ {.xfail-test}
-#[link_args = "-foo -bar -baz"]
-extern {}
-~~~
-
-Note that this feature is currently hidden behind the `feature(link_args)` gate
-because this is not a sanctioned way of performing linking. Right now rustc
-shells out to the system linker, so it makes sense to provide extra command line
-arguments, but this will not always be the case. In the future rustc may use
-LLVM directly to link native libraries in which case `link_args` will have no
-meaning.
-
-It is highly recommended to *not* use this attribute, and rather use the more
-formal `#[link(...)]` attribute on `extern` blocks instead.
-
-# Unsafe blocks
-
-Some operations, like dereferencing unsafe pointers or calling functions that have been marked
-unsafe are only allowed inside unsafe blocks. Unsafe blocks isolate unsafety and are a promise to
-the compiler that the unsafety does not leak out of the block.
-
-Unsafe functions, on the other hand, advertise it to the world. An unsafe function is written like
-this:
-
-~~~~
-unsafe fn kaboom(ptr: *int) -> int { *ptr }
-~~~~
-
-This function can only be called from an `unsafe` block or another `unsafe` function.
-
-# Accessing foreign globals
-
-Foreign APIs often export a global variable which could do something like track
-global state. In order to access these variables, you declare them in `extern`
-blocks with the `static` keyword:
-
-~~~{.xfail-test}
-use std::libc;
-
-#[link(name = "readline")]
-extern {
-    static rl_readline_version: libc::c_int;
-}
-
-fn main() {
-    println!("You have readline version {} installed.",
-             rl_readline_version as int);
-}
-~~~
-
-Alternatively, you may need to alter global state provided by a foreign
-interface. To do this, statics can be declared with `mut` so rust can mutate
-them.
-
-~~~{.xfail-test}
-use std::libc;
-use std::ptr;
-
-#[link(name = "readline")]
-extern {
-    static mut rl_prompt: *libc::c_char;
-}
-
-fn main() {
-    do "[my-awesome-shell] $".as_c_str |buf| {
-        unsafe { rl_prompt = buf; }
-        // get a line, process it
-        unsafe { rl_prompt = ptr::null(); }
-    }
-}
-~~~
-
-# Foreign calling conventions
-
-Most foreign code exposes a C ABI, and Rust uses the platform's C calling convention by default when
-calling foreign functions. Some foreign functions, most notably the Windows API, use other calling
-conventions. Rust provides a way to tell the compiler which convention to use:
-
-~~~~
-#[cfg(target_os = "win32", target_arch = "x86")]
-#[link_name = "kernel32"]
-extern "stdcall" {
-    fn SetEnvironmentVariableA(n: *u8, v: *u8) -> std::libc::c_int;
-}
-~~~~
-
-This applies to the entire `extern` block. The list of supported ABI constraints
-are:
-
-* `stdcall`
-* `aapcs`
-* `cdecl`
-* `fastcall`
-* `Rust`
-* `rust-intrinsic`
-* `system`
-* `C`
-
-Most of the abis in this list are self-explanatory, but the `system` abi may
-seem a little odd. This constraint selects whatever the appropriate ABI is for
-interoperating with the target's libraries. For example, on win32 with a x86
-architecture, this means that the abi used would be `stdcall`. On x86_64,
-however, windows uses the `C` calling convention, so `C` would be used. This
-means that in our previous example, we could have used `extern "system" { ... }`
-to define a block for all windows systems, not just x86 ones.
-
-# Interoperability with foreign code
-
-Rust guarantees that the layout of a `struct` is compatible with the platform's representation in C.
-A `#[packed]` attribute is available, which will lay out the struct members without padding.
-However, there are currently no guarantees about the layout of an `enum`.
-
-Rust's owned and managed boxes use non-nullable pointers as handles which point to the contained
-object. However, they should not be manually created because they are managed by internal
-allocators. Borrowed pointers can safely be assumed to be non-nullable pointers directly to the
-type. However, breaking the borrow checking or mutability rules is not guaranteed to be safe, so
-prefer using raw pointers (`*`) if that's needed because the compiler can't make as many assumptions
-about them.
-
-Vectors and strings share the same basic memory layout, and utilities are available in the `vec` and
-`str` modules for working with C APIs. However, strings are not terminated with `\0`. If you need a
-NUL-terminated string for interoperability with C, you should use the `c_str::to_c_str` function.
-
-The standard library includes type aliases and function definitions for the C standard library in
-the `libc` module, and Rust links against `libc` and `libm` by default.
diff --git a/doc/tutorial-macros.md b/doc/tutorial-macros.md
deleted file mode 100644 (file)
index 0ad8adf..0000000
+++ /dev/null
@@ -1,407 +0,0 @@
-% Rust Macros Tutorial
-
-# Introduction
-
-Functions are the primary tool that programmers can use to build abstractions.
-Sometimes, however, programmers want to abstract over compile-time syntax
-rather than run-time values.
-Macros provide syntactic abstraction.
-For an example of how this can be useful, consider the following two code fragments,
-which both pattern-match on their input and both return early in one case,
-doing nothing otherwise:
-
-~~~~
-# enum t { special_a(uint), special_b(uint) };
-# fn f() -> uint {
-# let input_1 = special_a(0);
-# let input_2 = special_a(0);
-match input_1 {
-    special_a(x) => { return x; }
-    _ => {}
-}
-// ...
-match input_2 {
-    special_b(x) => { return x; }
-    _ => {}
-}
-# return 0u;
-# }
-~~~~
-
-This code could become tiresome if repeated many times.
-However, no function can capture its functionality to make it possible
-to abstract the repetition away.
-Rust's macro system, however, can eliminate the repetition. Macros are
-lightweight custom syntax extensions, themselves defined using the
-`macro_rules!` syntax extension. The following `early_return` macro captures
-the pattern in the above code:
-
-~~~~
-# enum t { special_a(uint), special_b(uint) };
-# fn f() -> uint {
-# let input_1 = special_a(0);
-# let input_2 = special_a(0);
-macro_rules! early_return(
-    ($inp:expr $sp:ident) => ( // invoke it like `(input_5 special_e)`
-        match $inp {
-            $sp(x) => { return x; }
-            _ => {}
-        }
-    );
-)
-// ...
-early_return!(input_1 special_a);
-// ...
-early_return!(input_2 special_b);
-# return 0;
-# }
-~~~~
-
-Macros are defined in pattern-matching style: in the above example, the text
-`($inp:expr $sp:ident)` that appears on the left-hand side of the `=>` is the
-*macro invocation syntax*, a pattern denoting how to write a call to the
-macro. The text on the right-hand side of the `=>`, beginning with `match
-$inp`, is the *macro transcription syntax*: what the macro expands to.
-
-# Invocation syntax
-
-The macro invocation syntax specifies the syntax for the arguments to the
-macro. It appears on the left-hand side of the `=>` in a macro definition. It
-conforms to the following rules:
-
-1. It must be surrounded by parentheses.
-2. `$` has special meaning (described below).
-3. The `()`s, `[]`s, and `{}`s it contains must balance. For example, `([)` is
-forbidden.
-
-Otherwise, the invocation syntax is free-form.
-
-To take as an argument a fragment of Rust code, write `$` followed by a name
- (for use on the right-hand side), followed by a `:`, followed by a *fragment
- specifier*. The fragment specifier denotes the sort of fragment to match. The
- most common fragment specifiers are:
-
-* `ident` (an identifier, referring to a variable or item. Examples: `f`, `x`,
-  `foo`.)
-* `expr` (an expression. Examples: `2 + 2`; `if true then { 1 } else { 2 }`;
-  `f(42)`.)
-* `ty` (a type. Examples: `int`, `~[(char, ~str)]`, `&T`.)
-* `pat` (a pattern, usually appearing in a `match` or on the left-hand side of
-  a declaration. Examples: `Some(t)`; `(17, 'a')`; `_`.)
-* `block` (a sequence of actions. Example: `{ log(error, "hi"); return 12; }`)
-
-The parser interprets any token that's not preceded by a `$` literally. Rust's usual
-rules of tokenization apply,
-
-So `($x:ident -> (($e:expr)))`, though excessively fancy, would designate a macro
-that could be invoked like: `my_macro!(i->(( 2+2 )))`.
-
-## Invocation location
-
-A macro invocation may take the place of (and therefore expand to)
-an expression, an item, or a statement.
-The Rust parser will parse the macro invocation as a "placeholder"
-for whichever of those three nonterminals is appropriate for the location.
-
-At expansion time, the output of the macro will be parsed as whichever of the
-three nonterminals it stands in for. This means that a single macro might,
-for example, expand to an item or an expression, depending on its arguments
-(and cause a syntax error if it is called with the wrong argument for its
-location). Although this behavior sounds excessively dynamic, it is known to
-be useful under some circumstances.
-
-
-# Transcription syntax
-
-The right-hand side of the `=>` follows the same rules as the left-hand side,
-except that a `$` need only be followed by the name of the syntactic fragment
-to transcribe into the macro expansion; its type need not be repeated.
-
-The right-hand side must be enclosed by delimiters, which the transcriber ignores.
-Therefore `() => ((1,2,3))` is a macro that expands to a tuple expression,
-`() => (let $x=$val)` is a macro that expands to a statement,
-and `() => (1,2,3)` is a macro that expands to a syntax error
-(since the transcriber interprets the parentheses on the right-hand-size as delimiters,
-and `1,2,3` is not a valid Rust expression on its own).
-
-Except for permissibility of `$name` (and `$(...)*`, discussed below), the
-right-hand side of a macro definition is ordinary Rust syntax. In particular,
-macro invocations (including invocations of the macro currently being defined)
-are permitted in expression, statement, and item locations. However, nothing
-else about the code is examined or executed by the macro system; execution
-still has to wait until run-time.
-
-## Interpolation location
-
-The interpolation `$argument_name` may appear in any location consistent with
-its fragment specifier (i.e., if it is specified as `ident`, it may be used
-anywhere an identifier is permitted).
-
-# Multiplicity
-
-## Invocation
-
-Going back to the motivating example, recall that `early_return` expanded into
-a `match` that would `return` if the `match`'s scrutinee matched the
-"special case" identifier provided as the second argument to `early_return`,
-and do nothing otherwise. Now suppose that we wanted to write a
-version of `early_return` that could handle a variable number of "special"
-cases.
-
-The syntax `$(...)*` on the left-hand side of the `=>` in a macro definition
-accepts zero or more occurrences of its contents. It works much
-like the `*` operator in regular expressions. It also supports a
-separator token (a comma-separated list could be written `$(...),*`), and `+`
-instead of `*` to mean "at least one".
-
-~~~~
-# enum t { special_a(uint),special_b(uint),special_c(uint),special_d(uint)};
-# fn f() -> uint {
-# let input_1 = special_a(0);
-# let input_2 = special_a(0);
-macro_rules! early_return(
-    ($inp:expr, [ $($sp:ident)|+ ]) => (
-        match $inp {
-            $(
-                $sp(x) => { return x; }
-            )+
-            _ => {}
-        }
-    );
-)
-// ...
-early_return!(input_1, [special_a|special_c|special_d]);
-// ...
-early_return!(input_2, [special_b]);
-# return 0;
-# }
-~~~~
-
-### Transcription
-
-As the above example demonstrates, `$(...)*` is also valid on the right-hand
-side of a macro definition. The behavior of `*` in transcription,
-especially in cases where multiple `*`s are nested, and multiple different
-names are involved, can seem somewhat magical and intuitive at first. The
-system that interprets them is called "Macro By Example". The two rules to
-keep in mind are (1) the behavior of `$(...)*` is to walk through one "layer"
-of repetitions for all of the `$name`s it contains in lockstep, and (2) each
-`$name` must be under at least as many `$(...)*`s as it was matched against.
-If it is under more, it'll be repeated, as appropriate.
-
-## Parsing limitations
-
-
-For technical reasons, there are two limitations to the treatment of syntax
-fragments by the macro parser:
-
-1. The parser will always parse as much as possible of a Rust syntactic
-fragment. For example, if the comma were omitted from the syntax of
-`early_return!` above, `input_1 [` would've been interpreted as the beginning
-of an array index. In fact, invoking the macro would have been impossible.
-2. The parser must have eliminated all ambiguity by the time it reaches a
-`$name:fragment_specifier` declaration. This limitation can result in parse
-errors when declarations occur at the beginning of, or immediately after,
-a `$(...)*`. For example, the grammar `$($t:ty)* $e:expr` will always fail to
-parse because the parser would be forced to choose between parsing `t` and
-parsing `e`. Changing the invocation syntax to require a distinctive token in
-front can solve the problem. In the above example, `$(T $t:ty)* E $e:exp`
-solves the problem.
-
-# Macro argument pattern matching
-
-## Motivation
-
-Now consider code like the following:
-
-~~~~
-# enum t1 { good_1(t2, uint), bad_1 };
-# struct t2 { body: t3 }
-# enum t3 { good_2(uint), bad_2};
-# fn f(x: t1) -> uint {
-match x {
-    good_1(g1, val) => {
-        match g1.body {
-            good_2(result) => {
-                // complicated stuff goes here
-                return result + val;
-            },
-            _ => fail!("Didn't get good_2")
-        }
-    }
-    _ => return 0 // default value
-}
-# }
-~~~~
-
-All the complicated stuff is deeply indented, and the error-handling code is
-separated from matches that fail. We'd like to write a macro that performs
-a match, but with a syntax that suits the problem better. The following macro
-can solve the problem:
-
-~~~~
-macro_rules! biased_match (
-    // special case: `let (x) = ...` is illegal, so use `let x = ...` instead
-    ( ($e:expr) ~ ($p:pat) else $err:stmt ;
-      binds $bind_res:ident
-    ) => (
-        let $bind_res = match $e {
-            $p => ( $bind_res ),
-            _ => { $err }
-        };
-    );
-    // more than one name; use a tuple
-    ( ($e:expr) ~ ($p:pat) else $err:stmt ;
-      binds $( $bind_res:ident ),*
-    ) => (
-        let ( $( $bind_res ),* ) = match $e {
-            $p => ( $( $bind_res ),* ),
-            _ => { $err }
-        };
-    )
-)
-
-# enum t1 { good_1(t2, uint), bad_1 };
-# struct t2 { body: t3 }
-# enum t3 { good_2(uint), bad_2};
-# fn f(x: t1) -> uint {
-biased_match!((x)       ~ (good_1(g1, val)) else { return 0 };
-              binds g1, val )
-biased_match!((g1.body) ~ (good_2(result) )
-                  else { fail!("Didn't get good_2") };
-              binds result )
-// complicated stuff goes here
-return result + val;
-# }
-~~~~
-
-This solves the indentation problem. But if we have a lot of chained matches
-like this, we might prefer to write a single macro invocation. The input
-pattern we want is clear:
-~~~~
-# macro_rules! b(
-    ( $( ($e:expr) ~ ($p:pat) else $err:stmt ; )*
-      binds $( $bind_res:ident ),*
-    )
-# => (0))
-~~~~
-
-However, it's not possible to directly expand to nested match statements. But
-there is a solution.
-
-## The recursive approach to macro writing
-
-A macro may accept multiple different input grammars. The first one to
-successfully match the actual argument to a macro invocation is the one that
-"wins".
-
-In the case of the example above, we want to write a recursive macro to
-process the semicolon-terminated lines, one-by-one. So, we want the following
-input patterns:
-
-~~~~
-# macro_rules! b(
-    ( binds $( $bind_res:ident ),* )
-# => (0))
-~~~~
-...and:
-
-~~~~
-# macro_rules! b(
-    (    ($e     :expr) ~ ($p     :pat) else $err     :stmt ;
-      $( ($e_rest:expr) ~ ($p_rest:pat) else $err_rest:stmt ; )*
-      binds  $( $bind_res:ident ),*
-    )
-# => (0))
-~~~~
-
-The resulting macro looks like this. Note that the separation into
-`biased_match!` and `biased_match_rec!` occurs only because we have an outer
-piece of syntax (the `let`) which we only want to transcribe once.
-
-~~~~
-
-macro_rules! biased_match_rec (
-    // Handle the first layer
-    (   ($e     :expr) ~ ($p     :pat) else $err     :stmt ;
-     $( ($e_rest:expr) ~ ($p_rest:pat) else $err_rest:stmt ; )*
-     binds $( $bind_res:ident ),*
-    ) => (
-        match $e {
-            $p => {
-                // Recursively handle the next layer
-                biased_match_rec!($( ($e_rest) ~ ($p_rest) else $err_rest ; )*
-                                  binds $( $bind_res ),*
-                )
-            }
-            _ => { $err }
-        }
-    );
-    ( binds $( $bind_res:ident ),* ) => ( ($( $bind_res ),*) )
-)
-
-// Wrap the whole thing in a `let`.
-macro_rules! biased_match (
-    // special case: `let (x) = ...` is illegal, so use `let x = ...` instead
-    ( $( ($e:expr) ~ ($p:pat) else $err:stmt ; )*
-      binds $bind_res:ident
-    ) => (
-        let ( $( $bind_res ),* ) = biased_match_rec!(
-            $( ($e) ~ ($p) else $err ; )*
-            binds $bind_res
-        );
-    );
-    // more than one name: use a tuple
-    ( $( ($e:expr) ~ ($p:pat) else $err:stmt ; )*
-      binds  $( $bind_res:ident ),*
-    ) => (
-        let ( $( $bind_res ),* ) = biased_match_rec!(
-            $( ($e) ~ ($p) else $err ; )*
-            binds $( $bind_res ),*
-        );
-    )
-)
-
-
-# enum t1 { good_1(t2, uint), bad_1 };
-# struct t2 { body: t3 }
-# enum t3 { good_2(uint), bad_2};
-# fn f(x: t1) -> uint {
-biased_match!(
-    (x)       ~ (good_1(g1, val)) else { return 0 };
-    (g1.body) ~ (good_2(result) ) else { fail!("Didn't get good_2") };
-    binds val, result )
-// complicated stuff goes here
-return result + val;
-# }
-~~~~
-
-This technique applies to many cases where transcribing a result all at once is not possible.
-The resulting code resembles ordinary functional programming in some respects,
-but has some important differences from functional programming.
-
-The first difference is important, but also easy to forget: the transcription
-(right-hand) side of a `macro_rules!` rule is literal syntax, which can only
-be executed at run-time. If a piece of transcription syntax does not itself
-appear inside another macro invocation, it will become part of the final
-program. If it is inside a macro invocation (for example, the recursive
-invocation of `biased_match_rec!`), it does have the opportunity to affect
-transcription, but only through the process of attempted pattern matching.
-
-The second, related, difference is that the evaluation order of macros feels
-"backwards" compared to ordinary programming. Given an invocation
-`m1!(m2!())`, the expander first expands `m1!`, giving it as input the literal
-syntax `m2!()`. If it transcribes its argument unchanged into an appropriate
-position (in particular, not as an argument to yet another macro invocation),
-the expander will then proceed to evaluate `m2!()` (along with any other macro
-invocations `m1!(m2!())` produced).
-
-# A final note
-
-Macros, as currently implemented, are not for the faint of heart. Even
-ordinary syntax errors can be more difficult to debug when they occur inside a
-macro, and errors caused by parse problems in generated code can be very
-tricky. Invoking the `log_syntax!` macro can help elucidate intermediate
-states, invoking `trace_macros!(true)` will automatically print those
-intermediate states out, and passing the flag `--pretty expanded` as a
-command-line argument to the compiler will show the result of expansion.
diff --git a/doc/tutorial-rustpkg.md b/doc/tutorial-rustpkg.md
deleted file mode 100644 (file)
index 1cd3209..0000000
+++ /dev/null
@@ -1,270 +0,0 @@
-% Rust Packaging Tutorial
-
-# Introduction
-
-Sharing is caring. Rust comes with a tool, `rustpkg`, which allows you to
-package up your Rust code and share it with other people. This tutorial will
-get you started on all of the concepts and commands you need to give the gift
-of Rust code to someone else.
-
-# Installing External Packages
-
-First, let's try to use an external package somehow. I've made a sample package
-called `hello` to demonstrate how to do so.  Here's how `hello` is used:
-
-~~~~
-extern mod hello;
-
-fn main() {
-    hello::world();
-}
-~~~~
-
-Easy! But if you try to compile this, you'll get an error:
-
-~~~~ {.notrust}
-$ rustc main.rs 
-main.rs:1:0: 1:17 error: can't find crate for `hello`
-main.rs:1 extern mod hello;
-          ^~~~~~~~~~~~~~~~~
-~~~~
-
-This makes sense, as we haven't gotten it from anywhere yet!  Luckily for us,
-`rustpkg` has an easy way to fetch others' code: the `install` command. It's
-used like this:
-
-~~~ {.notrust}
-$ rustpkg install PKG_ID
-~~~
-
-This will install a package named `PKG_ID` into your current Rust environment.
-I called it `PKG_ID` in this example because `rustpkg` calls this a 'package
-identifier.' When using it with an external package like this, it's often a
-URI fragment.  You see, Rust has no central authority for packages. You can
-build your own `hello` library if you want, and that's fine. We'd both host
-them in different places and different projects would rely on whichever version
-they preferred.
-
-To install the `hello` library, simply run this in your terminal:
-
-~~~ {.notrust}
-$ rustpkg install github.com/steveklabnik/hello
-~~~
-
-You should see a message that looks like this:
-
-~~~ {.notrust}
-note: Installed package github.com/steveklabnik/hello-0.1 to /some/path/.rust
-~~~
-
-Now, compiling our example should work:
-
-~~~ {.notrust}
-$ rustc main.rs
-$ ./main 
-Hello, world.
-~~~
-
-Simple! That's all it takes.
-
-# Workspaces
-
-Before we can talk about how to make packages of your own, you have to
-understand the big concept with `rustpkg`: workspaces. A 'workspace' is simply
-a directory that has certain sub-directories that `rustpkg` expects. Different
-Rust projects will go into different workspaces.
-
-A workspace consists of any directory that has the following
-directories:
-
-* `src`: The directory where all the source code goes.
-* `build`: This directory contains all of the build output.
-* `lib`: The directory where any libraries distributed with the package go.
-* `bin`: This directory holds any binaries distributed with the package.
-
-There are also default file names you'll want to follow as well:
-
-* `main.rs`: A file that's going to become an executable.
-* `lib.rs`: A file that's going to become a library.
-
-# Building your own Package
-
-Now that you've got workspaces down, let's build your own copy of `hello`. Go
-to wherever you keep your personal projects, and let's make all of the
-directories we'll need. I'll refer to this personal project directory as
-`~/src` for the rest of this tutorial.
-
-## Creating our workspace
-
-~~~ {.notrust}
-$ cd ~/src
-$ mkdir -p hello/src/hello
-$ cd hello
-~~~
-
-Easy enough! Let's do one or two more things that are nice to do:
-
-~~~ {.notrust}
-$ git init .
-$ cat > README.md
-# hello
-
-A simple package for Rust.
-
-## Installation
-
-```
-$ rustpkg install github.com/YOUR_USERNAME/hello
-```
-^D
-$ cat > .gitignore
-.rust
-build
-^D
-$ git commit -am "Initial commit."
-~~~
-
-If you're not familliar with the `cat >` idiom, it will make files with the
-text you type inside. Control-D (`^D`) ends the text for the file.
-
-Anyway, we've got a README and a `.gitignore`. Let's talk about that
-`.gitignore` for a minute: we are ignoring two directories, `build` and
-`.rust`. `build`, as we discussed earlier, is for build artifacts, and we don't
-want to check those into a repository. `.rust` is a directory that `rustpkg`
-uses to keep track of its own settings, as well as the source code of any other
-external packages that this workspace uses. This is where that `rustpkg
-install` puts all of its files. Those are also not to go into our repository,
-so we ignore it all as well.
-
-Next, let's add a source file:
-
-~~~
-#[desc = "A hello world Rust package."];
-#[license = "MIT"];
-
-pub fn world() {
-    println("Hello, world.");
-}
-~~~
-
-Put this into `src/hello/lib.rs`. Let's talk about each of these attributes:
-
-## Crate attributes for packages
-
-`license` is equally simple: the license we want this code to have. I chose MIT
-here, but you should pick whatever license makes the most sense for you.
-
-`desc` is a description of the package and what it does. This should just be a
-sentence or two.
-
-## Building your package
-
-Building your package is simple:
-
-~~~ {.notrust}
-$ rustpkg build hello
-~~~
-
-This will compile `src/hello/lib.rs` into a library. After this process
-completes, you'll want to check out `build`:
-
-~~~ {.notrust}
-$ ls build/x86_64-unknown-linux-gnu/hello/
-libhello-ed8619dad9ce7d58-0.1.0.so
-~~~
-
-This directory naming structure is called a 'build triple,' and is because I'm
-on 64 bit Linux. Yours may differ based on platform.
-
-You'll also notice that `src/hello/lib.rs` turned into
-`libhello-ed8619dad9ce7d58-0.1.0.so`. This is a simple combination of the
-library name, a hash of its content, and the version.
-
-Now that your library builds, you'll want to commit:
-
-~~~ {.notrust}
-$ git add src
-$ git commit -m "Adding source code."
-~~~
-
-If you're using GitHub, after creating the project, do this:
-
-~~~ {.notrust}
-$ git remote add origin git@github.com:YOUR_USERNAME/hello.git
-$ git push origin -u master
-~~~
-
-Now you can install and use it! Go anywhere else in your filesystem:
-
-~~~ {.notrust}
-$ cd ~/src/foo
-$ rustpkg install github.com/YOUR_USERNAME/hello
-WARNING: The Rust package manager is experimental and may be unstable
-note: Installed package github.com/YOUR_USERNAME/hello-0.1 to /home/yourusername/src/hello/.rust
-~~~
-
-That's it!
-
-# Testing your Package
-
-Testing your package is simple as well. First, let's change `src/hello/lib.rs` to contain
-a function that can be sensibly tested:
-
-~~~
-#[desc = "A Rust package for determining whether unsigned integers are even."];
-#[license = "MIT"];
-
-pub fn is_even(i: uint) -> bool {
-    i % 2 == 0
-}
-~~~
-
-Once you've edited `lib.rs`, you can create a second crate file, `src/hello/test.rs`,
-to put tests in:
-
-~~~
-#[license = "MIT"];
-extern mod hello;
-use hello::is_even;
-
-#[test]
-fn test_is_even() {
-    assert!(is_even(0));
-    assert!(!is_even(1));
-    assert!(is_even(2));
-}
-~~~
-
-Note that you have to import the crate you just created in `lib.rs` with the
-`extern mod hello` directive. That's because you're putting the tests in a different
-crate from the main library that you created.
-
-Now, you can use the `rustpkg test` command to build this test crate (and anything else
-it depends on) and run the tests, all in one step:
-
-~~~ {.notrust}
-$ rustpkg test hello
-WARNING: The Rust package manager is experimental and may be unstable
-note: Installed package hello-0.1 to /Users/tjc/.rust
-
-running 1 test
-test test_is_even ... ok
-
-test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
-~~~
-
-# More resources
-
-There's a lot more going on with `rustpkg`, this is just to get you started.
-Check out [the rustpkg manual](rustpkg.html) for the full details on how to
-customize `rustpkg`.
-
-A tag was created on GitHub specifically for `rustpkg`-related issues. You can
-[see all the Issues for rustpkg
-here](https://github.com/mozilla/rust/issues?direction=desc&labels=A-pkg&sort=created&state=open),
-with bugs as well as new feature plans. `rustpkg` is still under development,
-and so may be a bit flaky at the moment.
-
-You may also want to check out [this blog
-post](http://tim.dreamwidth.org/1820526.html), which contains some of the early
-design decisions and justifications.
diff --git a/doc/tutorial-tasks.md b/doc/tutorial-tasks.md
deleted file mode 100644 (file)
index 6213a0c..0000000
+++ /dev/null
@@ -1,515 +0,0 @@
-% Rust Tasks and Communication Tutorial
-
-# Introduction
-
-Rust provides safe concurrency through a combination
-of lightweight, memory-isolated tasks and message passing.
-This tutorial will describe the concurrency model in Rust, how it
-relates to the Rust type system, and introduce
-the fundamental library abstractions for constructing concurrent programs.
-
-Rust tasks are not the same as traditional threads: rather,
-they are considered _green threads_, lightweight units of execution that the Rust
-runtime schedules cooperatively onto a small number of operating system threads.
-On a multi-core system Rust tasks will be scheduled in parallel by default.
-Because tasks are significantly
-cheaper to create than traditional threads, Rust can create hundreds of
-thousands of concurrent tasks on a typical 32-bit system.
-In general, all Rust code executes inside a task, including the `main` function.
-
-In order to make efficient use of memory Rust tasks have dynamically sized stacks.
-A task begins its life with a small
-amount of stack space (currently in the low thousands of bytes, depending on
-platform), and acquires more stack as needed.
-Unlike in languages such as C, a Rust task cannot accidentally write to
-memory beyond the end of the stack, causing crashes or worse.
-
-Tasks provide failure isolation and recovery. When a fatal error occurs in Rust
-code as a result of an explicit call to `fail!()`, an assertion failure, or
-another invalid operation, the runtime system destroys the entire
-task. Unlike in languages such as Java and C++, there is no way to `catch` an
-exception. Instead, tasks may monitor each other for failure.
-
-Tasks use Rust's type system to provide strong memory safety guarantees. In
-particular, the type system guarantees that tasks cannot share mutable state
-with each other. Tasks communicate with each other by transferring _owned_
-data through the global _exchange heap_.
-
-## A note about the libraries
-
-While Rust's type system provides the building blocks needed for safe
-and efficient tasks, all of the task functionality itself is implemented
-in the standard and extra libraries, which are still under development
-and do not always present a consistent or complete interface.
-
-For your reference, these are the standard modules involved in Rust
-concurrency at this writing:
-
-* [`std::task`] - All code relating to tasks and task scheduling,
-* [`std::comm`] - The message passing interface,
-* [`extra::comm`] - Additional messaging types based on `std::comm`,
-* [`extra::sync`] - More exotic synchronization tools, including locks,
-* [`extra::arc`] - The Arc (atomically reference counted) type,
-  for safely sharing immutable data,
-* [`extra::future`] - A type representing values that may be computed concurrently and retrieved at a later time.
-
-[`std::task`]: std/task/index.html
-[`std::comm`]: std/comm/index.html
-[`extra::comm`]: extra/comm/index.html
-[`extra::sync`]: extra/sync/index.html
-[`extra::arc`]: extra/arc/index.html
-[`extra::future`]: extra/future/index.html
-
-# Basics
-
-The programming interface for creating and managing tasks lives
-in the `task` module of the `std` library, and is thus available to all
-Rust code by default. At its simplest, creating a task is a matter of
-calling the `spawn` function with a closure argument. `spawn` executes the
-closure in the new task.
-
-~~~~
-# use std::task::spawn;
-
-// Print something profound in a different task using a named function
-fn print_message() { println("I am running in a different task!"); }
-spawn(print_message);
-
-// Print something more profound in a different task using a lambda expression
-spawn(proc() println("I am also running in a different task!") );
-
-// The canonical way to spawn is using `do` notation
-do spawn {
-    println("I too am running in a different task!");
-}
-~~~~
-
-In Rust, there is nothing special about creating tasks: a task is not a
-concept that appears in the language semantics. Instead, Rust's type system
-provides all the tools necessary to implement safe concurrency: particularly,
-_owned types_. The language leaves the implementation details to the standard
-library.
-
-The `spawn` function has a very simple type signature: `fn spawn(f:
-proc())`. Because it accepts only owned closures, and owned closures
-contain only owned data, `spawn` can safely move the entire closure
-and all its associated state into an entirely different task for
-execution. Like any closure, the function passed to `spawn` may capture
-an environment that it carries across tasks.
-
-~~~
-# use std::task::spawn;
-# fn generate_task_number() -> int { 0 }
-// Generate some state locally
-let child_task_number = generate_task_number();
-
-do spawn {
-    // Capture it in the remote task
-    println!("I am child number {}", child_task_number);
-}
-~~~
-
-## Communication
-
-Now that we have spawned a new task, it would be nice if we could
-communicate with it. Recall that Rust does not have shared mutable
-state, so one task may not manipulate variables owned by another task.
-Instead we use *pipes*.
-
-A pipe is simply a pair of endpoints: one for sending messages and another for
-receiving messages. Pipes are low-level communication building-blocks and so
-come in a variety of forms, each one appropriate for a different use case. In
-what follows, we cover the most commonly used varieties.
-
-The simplest way to create a pipe is to use `Chan::new`
-function to create a `(Port, Chan)` pair. In Rust parlance, a *channel*
-is a sending endpoint of a pipe, and a *port* is the receiving
-endpoint. Consider the following example of calculating two results
-concurrently:
-
-~~~~
-# use std::task::spawn;
-
-let (port, chan): (Port<int>, Chan<int>) = Chan::new();
-
-do spawn || {
-    let result = some_expensive_computation();
-    chan.send(result);
-}
-
-some_other_expensive_computation();
-let result = port.recv();
-# fn some_expensive_computation() -> int { 42 }
-# fn some_other_expensive_computation() {}
-~~~~
-
-Let's examine this example in detail. First, the `let` statement creates a
-stream for sending and receiving integers (the left-hand side of the `let`,
-`(chan, port)`, is an example of a *destructuring let*: the pattern separates
-a tuple into its component parts).
-
-~~~~
-let (port, chan): (Port<int>, Chan<int>) = Chan::new();
-~~~~
-
-The child task will use the channel to send data to the parent task,
-which will wait to receive the data on the port. The next statement
-spawns the child task.
-
-~~~~
-# use std::task::spawn;
-# fn some_expensive_computation() -> int { 42 }
-# let (port, chan) = Chan::new();
-do spawn || {
-    let result = some_expensive_computation();
-    chan.send(result);
-}
-~~~~
-
-Notice that the creation of the task closure transfers `chan` to the child
-task implicitly: the closure captures `chan` in its environment. Both `Chan`
-and `Port` are sendable types and may be captured into tasks or otherwise
-transferred between them. In the example, the child task runs an expensive
-computation, then sends the result over the captured channel.
-
-Finally, the parent continues with some other expensive
-computation, then waits for the child's result to arrive on the
-port:
-
-~~~~
-# fn some_other_expensive_computation() {}
-# let (port, chan) = Chan::<int>::new();
-# chan.send(0);
-some_other_expensive_computation();
-let result = port.recv();
-~~~~
-
-The `Port` and `Chan` pair created by `Chan::new` enables efficient
-communication between a single sender and a single receiver, but multiple
-senders cannot use a single `Chan`, and multiple receivers cannot use a single
-`Port`.  What if our example needed to compute multiple results across a number
-of tasks? The following program is ill-typed:
-
-~~~ {.xfail-test}
-# use std::task::{spawn};
-# fn some_expensive_computation() -> int { 42 }
-let (port, chan) = Chan::new();
-
-do spawn {
-    chan.send(some_expensive_computation());
-}
-
-// ERROR! The previous spawn statement already owns the channel,
-// so the compiler will not allow it to be captured again
-do spawn {
-    chan.send(some_expensive_computation());
-}
-~~~
-
-Instead we can use a `SharedChan`, a type that allows a single
-`Chan` to be shared by multiple senders.
-
-~~~
-# use std::task::spawn;
-
-let (port, chan) = SharedChan::new();
-
-for init_val in range(0u, 3) {
-    // Create a new channel handle to distribute to the child task
-    let child_chan = chan.clone();
-    do spawn {
-        child_chan.send(some_expensive_computation(init_val));
-    }
-}
-
-let result = port.recv() + port.recv() + port.recv();
-# fn some_expensive_computation(_i: uint) -> int { 42 }
-~~~
-
-Here we transfer ownership of the channel into a new `SharedChan` value.  Like
-`Chan`, `SharedChan` is a non-copyable, owned type (sometimes also referred to
-as an *affine* or *linear* type). Unlike with `Chan`, though, the programmer
-may duplicate a `SharedChan`, with the `clone()` method.  A cloned
-`SharedChan` produces a new handle to the same channel, allowing multiple
-tasks to send data to a single port.  Between `spawn`, `Chan` and
-`SharedChan`, we have enough tools to implement many useful concurrency
-patterns.
-
-Note that the above `SharedChan` example is somewhat contrived since
-you could also simply use three `Chan` pairs, but it serves to
-illustrate the point. For reference, written with multiple streams, it
-might look like the example below.
-
-~~~
-# use std::task::spawn;
-# use std::vec;
-
-// Create a vector of ports, one for each child task
-let ports = vec::from_fn(3, |init_val| {
-    let (port, chan) = Chan::new();
-    do spawn {
-        chan.send(some_expensive_computation(init_val));
-    }
-    port
-});
-
-// Wait on each port, accumulating the results
-let result = ports.iter().fold(0, |accum, port| accum + port.recv() );
-# fn some_expensive_computation(_i: uint) -> int { 42 }
-~~~
-
-## Backgrounding computations: Futures
-With `extra::future`, rust has a mechanism for requesting a computation and getting the result
-later.
-
-The basic example below illustrates this.
-~~~
-# fn make_a_sandwich() {};
-fn fib(n: u64) -> u64 {
-    // lengthy computation returning an uint
-    12586269025
-}
-
-let mut delayed_fib = extra::future::Future::spawn(proc() fib(50));
-make_a_sandwich();
-println!("fib(50) = {:?}", delayed_fib.get())
-~~~
-
-The call to `future::spawn` returns immediately a `future` object regardless of how long it
-takes to run `fib(50)`. You can then make yourself a sandwich while the computation of `fib` is
-running. The result of the execution of the method is obtained by calling `get` on the future.
-This call will block until the value is available (*i.e.* the computation is complete). Note that
-the future needs to be mutable so that it can save the result for next time `get` is called.
-
-Here is another example showing how futures allow you to background computations. The workload will
-be distributed on the available cores.
-~~~
-# use std::vec;
-fn partial_sum(start: uint) -> f64 {
-    let mut local_sum = 0f64;
-    for num in range(start*100000, (start+1)*100000) {
-        local_sum += (num as f64 + 1.0).pow(&-2.0);
-    }
-    local_sum
-}
-
-fn main() {
-    let mut futures = vec::from_fn(1000, |ind| do extra::future::Future::spawn { partial_sum(ind) });
-
-    let mut final_res = 0f64;
-    for ft in futures.mut_iter()  {
-        final_res += ft.get();
-    }
-    println!("π^2/6 is not far from : {}", final_res);
-}
-~~~
-
-## Sharing immutable data without copy: Arc
-
-To share immutable data between tasks, a first approach would be to only use pipes as we have seen
-previously. A copy of the data to share would then be made for each task. In some cases, this would
-add up to a significant amount of wasted memory and would require copying the same data more than
-necessary.
-
-To tackle this issue, one can use an Atomically Reference Counted wrapper (`Arc`) as implemented in
-the `extra` library of Rust. With an Arc, the data will no longer be copied for each task. The Arc
-acts as a reference to the shared data and only this reference is shared and cloned.
-
-Here is a small example showing how to use Arcs. We wish to run concurrently several computations on
-a single large vector of floats. Each task needs the full vector to perform its duty.
-~~~
-# use std::vec;
-# use std::rand;
-use extra::arc::Arc;
-
-fn pnorm(nums: &~[f64], p: uint) -> f64 {
-    nums.iter().fold(0.0, |a,b| a+(*b).pow(&(p as f64)) ).pow(&(1.0 / (p as f64)))
-}
-
-fn main() {
-    let numbers = vec::from_fn(1000000, |_| rand::random::<f64>());
-    println!("Inf-norm = {}",  *numbers.iter().max().unwrap());
-
-    let numbers_arc = Arc::new(numbers);
-
-    for num in range(1u, 10) {
-        let (port, chan)  = Chan::new();
-        chan.send(numbers_arc.clone());
-
-        do spawn {
-            let local_arc : Arc<~[f64]> = port.recv();
-            let task_numbers = local_arc.get();
-            println!("{}-norm = {}", num, pnorm(task_numbers, num));
-        }
-    }
-}
-~~~
-
-The function `pnorm` performs a simple computation on the vector (it computes the sum of its items
-at the power given as argument and takes the inverse power of this value). The Arc on the vector is
-created by the line
-~~~
-# use extra::arc::Arc;
-# use std::vec;
-# use std::rand;
-# let numbers = vec::from_fn(1000000, |_| rand::random::<f64>());
-let numbers_arc=Arc::new(numbers);
-~~~
-and a clone of it is sent to each task
-~~~
-# use extra::arc::Arc;
-# use std::vec;
-# use std::rand;
-# let numbers=vec::from_fn(1000000, |_| rand::random::<f64>());
-# let numbers_arc = Arc::new(numbers);
-# let (port, chan)  = Chan::new();
-chan.send(numbers_arc.clone());
-~~~
-copying only the wrapper and not its contents.
-
-Each task recovers the underlying data by
-~~~
-# use extra::arc::Arc;
-# use std::vec;
-# use std::rand;
-# let numbers=vec::from_fn(1000000, |_| rand::random::<f64>());
-# let numbers_arc=Arc::new(numbers);
-# let (port, chan)  = Chan::new();
-# chan.send(numbers_arc.clone());
-# let local_arc : Arc<~[f64]> = port.recv();
-let task_numbers = local_arc.get();
-~~~
-and can use it as if it were local.
-
-The `arc` module also implements Arcs around mutable data that are not covered here.
-
-# Handling task failure
-
-Rust has a built-in mechanism for raising exceptions. The `fail!()` macro
-(which can also be written with an error string as an argument: `fail!(
-~reason)`) and the `assert!` construct (which effectively calls `fail!()`
-if a boolean expression is false) are both ways to raise exceptions. When a
-task raises an exception the task unwinds its stack---running destructors and
-freeing memory along the way---and then exits. Unlike exceptions in C++,
-exceptions in Rust are unrecoverable within a single task: once a task fails,
-there is no way to "catch" the exception.
-
-While it isn't possible for a task to recover from failure, tasks may notify
-each other of failure. The simplest way of handling task failure is with the
-`try` function, which is similar to `spawn`, but immediately blocks waiting
-for the child task to finish. `try` returns a value of type `Result<T,
-()>`. `Result` is an `enum` type with two variants: `Ok` and `Err`. In this
-case, because the type arguments to `Result` are `int` and `()`, callers can
-pattern-match on a result to check whether it's an `Ok` result with an `int`
-field (representing a successful result) or an `Err` result (representing
-termination with an error).
-
-~~~{.xfail-test .linked-failure}
-# use std::task;
-# fn some_condition() -> bool { false }
-# fn calculate_result() -> int { 0 }
-let result: Result<int, ()> = do task::try {
-    if some_condition() {
-        calculate_result()
-    } else {
-        fail!("oops!");
-    }
-};
-assert!(result.is_err());
-~~~
-
-Unlike `spawn`, the function spawned using `try` may return a value,
-which `try` will dutifully propagate back to the caller in a [`Result`]
-enum. If the child task terminates successfully, `try` will
-return an `Ok` result; if the child task fails, `try` will return
-an `Error` result.
-
-[`Result`]: std/result/index.html
-
-> ***Note:*** A failed task does not currently produce a useful error
-> value (`try` always returns `Err(())`). In the
-> future, it may be possible for tasks to intercept the value passed to
-> `fail!()`.
-
-TODO: Need discussion of `future_result` in order to make failure
-modes useful.
-
-But not all failures are created equal. In some cases you might need to
-abort the entire program (perhaps you're writing an assert which, if
-it trips, indicates an unrecoverable logic error); in other cases you
-might want to contain the failure at a certain boundary (perhaps a
-small piece of input from the outside world, which you happen to be
-processing in parallel, is malformed and its processing task can't
-proceed).
-
-## Creating a task with a bi-directional communication path
-
-A very common thing to do is to spawn a child task where the parent
-and child both need to exchange messages with each other. The
-function `extra::comm::DuplexStream()` supports this pattern.  We'll
-look briefly at how to use it.
-
-To see how `DuplexStream()` works, we will create a child task
-that repeatedly receives a `uint` message, converts it to a string, and sends
-the string in response.  The child terminates when it receives `0`.
-Here is the function that implements the child task:
-
-~~~{.xfail-test .linked-failure}
-# use extra::comm::DuplexStream;
-# use std::uint;
-fn stringifier(channel: &DuplexStream<~str, uint>) {
-    let mut value: uint;
-    loop {
-        value = channel.recv();
-        channel.send(uint::to_str(value));
-        if value == 0 { break; }
-    }
-}
-~~~~
-
-The implementation of `DuplexStream` supports both sending and
-receiving. The `stringifier` function takes a `DuplexStream` that can
-send strings (the first type parameter) and receive `uint` messages
-(the second type parameter). The body itself simply loops, reading
-from the channel and then sending its response back.  The actual
-response itself is simply the stringified version of the received value,
-`uint::to_str(value)`.
-
-Here is the code for the parent task:
-
-~~~{.xfail-test .linked-failure}
-# use std::task::spawn;
-# use std::uint;
-# use extra::comm::DuplexStream;
-# fn stringifier(channel: &DuplexStream<~str, uint>) {
-#     let mut value: uint;
-#     loop {
-#         value = channel.recv();
-#         channel.send(uint::to_str(value));
-#         if value == 0u { break; }
-#     }
-# }
-# fn main() {
-
-let (from_child, to_child) = DuplexStream::new();
-
-do spawn {
-    stringifier(&to_child);
-};
-
-from_child.send(22);
-assert!(from_child.recv() == ~"22");
-
-from_child.send(23);
-from_child.send(0);
-
-assert!(from_child.recv() == ~"23");
-assert!(from_child.recv() == ~"0");
-
-# }
-~~~~
-
-The parent task first calls `DuplexStream` to create a pair of bidirectional
-endpoints. It then uses `task::spawn` to create the child task, which captures
-one end of the communication channel.  As a result, both parent and child can
-send and receive data to and from the other.
diff --git a/doc/tutorial-testing.md b/doc/tutorial-testing.md
deleted file mode 100644 (file)
index b09ba60..0000000
+++ /dev/null
@@ -1,263 +0,0 @@
-% Rust Testing Tutorial
-
-# Quick start
-
-To create test functions, add a `#[test]` attribute like this:
-
-```rust
-fn return_two() -> int {
-    2
-}
-
-#[test]
-fn return_two_test() {
-    let x = return_two();
-    assert!(x == 2);
-}
-```
-
-To run these tests, use `rustc --test`:
-
-```
-$ rustc --test foo.rs; ./foo
-running 1 test
-test return_two_test ... ok
-
-test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
-```
-
-`rustc foo.rs` will *not* compile the tests, since `#[test]` implies
-`#[cfg(test)]`. The `--test` flag to `rustc` implies `--cfg test`.
-
-
-# Unit testing in Rust
-
-Rust has built in support for simple unit testing. Functions can be
-marked as unit tests using the 'test' attribute.
-
-```rust
-#[test]
-fn return_none_if_empty() {
-    // ... test code ...
-}
-```
-
-A test function's signature must have no arguments and no return
-value. To run the tests in a crate, it must be compiled with the
-'--test' flag: `rustc myprogram.rs --test -o myprogram-tests`. Running
-the resulting executable will run all the tests in the crate. A test
-is considered successful if its function returns; if the task running
-the test fails, through a call to `fail!`, a failed `check` or
-`assert`, or some other (`assert_eq`, `assert_approx_eq`, ...) means,
-then the test fails.
-
-When compiling a crate with the '--test' flag '--cfg test' is also
-implied, so that tests can be conditionally compiled.
-
-```rust
-#[cfg(test)]
-mod tests {
-    #[test]
-    fn return_none_if_empty() {
-      // ... test code ...
-    }
-}
-```
-
-Additionally #[test] items behave as if they also have the
-#[cfg(test)] attribute, and will not be compiled when the --test flag
-is not used.
-
-Tests that should not be run can be annotated with the 'ignore'
-attribute. The existence of these tests will be noted in the test
-runner output, but the test will not be run. Tests can also be ignored
-by configuration so, for example, to ignore a test on windows you can
-write `#[ignore(cfg(target_os = "win32"))]`.
-
-Tests that are intended to fail can be annotated with the
-'should_fail' attribute. The test will be run, and if it causes its
-task to fail then the test will be counted as successful; otherwise it
-will be counted as a failure. For example:
-
-```rust
-#[test]
-#[should_fail]
-fn test_out_of_bounds_failure() {
-    let v: [int] = [];
-    v[0];
-}
-```
-
-A test runner built with the '--test' flag supports a limited set of
-arguments to control which tests are run: the first free argument
-passed to a test runner specifies a filter used to narrow down the set
-of tests being run; the '--ignored' flag tells the test runner to run
-only tests with the 'ignore' attribute.
-
-## Parallelism
-
-By default, tests are run in parallel, which can make interpreting
-failure output difficult. In these cases you can set the
-`RUST_TEST_TASKS` environment variable to 1 to make the tests run
-sequentially.
-
-## Benchmarking
-
-The test runner also understands a simple form of benchmark execution.
-Benchmark functions are marked with the `#[bench]` attribute, rather
-than `#[test]`, and have a different form and meaning. They are
-compiled along with `#[test]` functions when a crate is compiled with
-`--test`, but they are not run by default. To run the benchmark
-component of your testsuite, pass `--bench` to the compiled test
-runner.
-
-The type signature of a benchmark function differs from a unit test:
-it takes a mutable reference to type `test::BenchHarness`. Inside the
-benchmark function, any time-variable or "setup" code should execute
-first, followed by a call to `iter` on the benchmark harness, passing
-a closure that contains the portion of the benchmark you wish to
-actually measure the per-iteration speed of.
-
-For benchmarks relating to processing/generating data, one can set the
-`bytes` field to the number of bytes consumed/produced in each
-iteration; this will used to show the throughput of the benchmark.
-This must be the amount used in each iteration, *not* the total
-amount.
-
-For example:
-
-```rust
-extern mod extra;
-use std::vec;
-
-#[bench]
-fn bench_sum_1024_ints(b: &mut extra::test::BenchHarness) {
-    let v = vec::from_fn(1024, |n| n);
-    b.iter(|| {v.iter().fold(0, |old, new| old + *new);} );
-}
-
-#[bench]
-fn initialise_a_vector(b: &mut extra::test::BenchHarness) {
-    b.iter(|| {vec::from_elem(1024, 0u64);} );
-    b.bytes = 1024 * 8;
-}
-```
-
-The benchmark runner will calibrate measurement of the benchmark
-function to run the `iter` block "enough" times to get a reliable
-measure of the per-iteration speed.
-
-Advice on writing benchmarks:
-
-  - Move setup code outside the `iter` loop; only put the part you
-    want to measure inside
-  - Make the code do "the same thing" on each iteration; do not
-    accumulate or change state
-  - Make the outer function idempotent too; the benchmark runner is
-    likely to run it many times
-  - Make the inner `iter` loop short and fast so benchmark runs are
-    fast and the calibrator can adjust the run-length at fine
-    resolution
-  - Make the code in the `iter` loop do something simple, to assist in
-    pinpointing performance improvements (or regressions)
-
-To run benchmarks, pass the `--bench` flag to the compiled
-test-runner. Benchmarks are compiled-in but not executed by default.
-
-## Examples
-
-### Typical test run
-
-```
-> mytests
-
-running 30 tests
-running driver::tests::mytest1 ... ok
-running driver::tests::mytest2 ... ignored
-... snip ...
-running driver::tests::mytest30 ... ok
-
-result: ok. 28 passed; 0 failed; 2 ignored
-```
-
-### Test run with failures
-
-```
-> mytests
-
-running 30 tests
-running driver::tests::mytest1 ... ok
-running driver::tests::mytest2 ... ignored
-... snip ...
-running driver::tests::mytest30 ... FAILED
-
-result: FAILED. 27 passed; 1 failed; 2 ignored
-```
-
-### Running ignored tests
-
-```
-> mytests --ignored
-
-running 2 tests
-running driver::tests::mytest2 ... failed
-running driver::tests::mytest10 ... ok
-
-result: FAILED. 1 passed; 1 failed; 0 ignored
-```
-
-### Running a subset of tests
-
-```
-> mytests mytest1
-
-running 11 tests
-running driver::tests::mytest1 ... ok
-running driver::tests::mytest10 ... ignored
-... snip ...
-running driver::tests::mytest19 ... ok
-
-result: ok. 11 passed; 0 failed; 1 ignored
-```
-
-### Running benchmarks
-
-```
-> mytests --bench
-
-running 2 tests
-test bench_sum_1024_ints ... bench: 709 ns/iter (+/- 82)
-test initialise_a_vector ... bench: 424 ns/iter (+/- 99) = 19320 MB/s
-
-test result: ok. 0 passed; 0 failed; 0 ignored; 2 measured
-```
-
-## Saving and ratcheting metrics
-
-When running benchmarks or other tests, the test runner can record
-per-test "metrics". Each metric is a scalar `f64` value, plus a noise
-value which represents uncertainty in the measurement. By default, all
-`#[bench]` benchmarks are recorded as metrics, which can be saved as
-JSON in an external file for further reporting.
-
-In addition, the test runner supports _ratcheting_ against a metrics
-file. Ratcheting is like saving metrics, except that after each run,
-if the output file already exists the results of the current run are
-compared against the contents of the existing file, and any regression
-_causes the testsuite to fail_. If the comparison passes -- if all
-metrics stayed the same (within noise) or improved -- then the metrics
-file is overwritten with the new values. In this way, a metrics file
-in your workspace can be used to ensure your work does not regress
-performance.
-
-Test runners take 3 options that are relevant to metrics:
-
-  - `--save-metrics=<file.json>` will save the metrics from a test run
-    to `file.json`
-  - `--ratchet-metrics=<file.json>` will ratchet the metrics against
-    the `file.json`
-  - `--ratchet-noise-percent=N` will override the noise measurements
-    in `file.json`, and consider a metric change less than `N%` to be
-    noise. This can be helpful if you are testing in a noisy
-    environment where the benchmark calibration loop cannot acquire a
-    clear enough signal.
index 0eb228d82059d3247b3a49c4051c608a2ec77811..e25ac009de231839060a6065335cc92b1b2f6f3c 100644 (file)
@@ -3035,8 +3035,6 @@ but for this tutorial it's only important to know that you can optionally annota
 extern mod rust = "github.com/mozilla/rust"; // pretend Rust is a simple library
 ~~~
 
-[rustpkg]: rustpkg.html
-
 ## Crate metadata and settings
 
 For every crate you can define a number of metadata items, such as link name, version or author.
@@ -3194,7 +3192,7 @@ re-export a bunch of 'officially blessed' crates that get managed with `rustpkg`
 # What next?
 
 Now that you know the essentials, check out any of the additional
-tutorials on individual topics.
+guides on individual topics.
 
 * [Borrowed pointers][borrow]
 * [Tasks and communication][tasks]
@@ -3209,14 +3207,14 @@ tutorials on individual topics.
 There is further documentation on the [wiki], however those tend to be even
 more out of date than this document.
 
-[borrow]: tutorial-borrowed-ptr.html
-[tasks]: tutorial-tasks.html
-[macros]: tutorial-macros.html
-[ffi]: tutorial-ffi.html
-[container]: tutorial-container.html
-[conditions]: tutorial-conditions.html
-[rustpkg]: tutorial-rustpkg.html
-[testing]: tutorial-testing.html
+[borrow]: guide-borrowed-ptr.html
+[tasks]: guide-tasks.html
+[macros]: guide-macros.html
+[ffi]: guide-ffi.html
+[container]: guide-container.html
+[conditions]: guide-conditions.html
+[rustpkg]: guide-rustpkg.html
+[testing]: guide-testing.html
 [rustdoc]: rustdoc.html
 
 [wiki]: https://github.com/mozilla/rust/wiki/Docs
index f211af700b9363ec34401245b42352048594cff5..2e109859b06e73b591fae755db163eb6853cca95 100644 (file)
@@ -17,7 +17,11 @@ CDOCS :=
 DOCS_L10N :=
 
 BASE_DOC_OPTS := --from=markdown --standalone --toc --number-sections
-HTML_OPTS = $(BASE_DOC_OPTS) --to=html5  --section-divs --css=rust.css  --include-before-body=doc/version_info.html --include-in-header=doc/favicon.inc
+
+HTML_OPTS = $(BASE_DOC_OPTS)   --to=html5  --section-divs --css=rust.css  \
+                                                                                                                       --include-before-body=doc/version_info.html \
+                                                                                                                       --include-in-header=doc/favicon.inc
+
 TEX_OPTS = $(BASE_DOC_OPTS) --to=latex
 EPUB_OPTS = $(BASE_DOC_OPTS) --to=epub
 
@@ -112,57 +116,59 @@ doc/l10n/ja/tutorial.html: doc/l10n/ja/tutorial.md doc/version_info.html doc/rus
            --include-before-body=doc/version_info.html \
            --output=$@
 
-DOCS += doc/tutorial-macros.html
-doc/tutorial-macros.html: tutorial-macros.md doc/version_info.html doc/rust.css \
+# Guides
+
+DOCS += doc/guide-macros.html
+doc/guide-macros.html: $(S)doc/guide-macros.md doc/version_info.html doc/rust.css \
                                doc/favicon.inc
        @$(call E, pandoc: $@)
        $(Q)$(CFG_NODE) $(S)doc/prep.js --highlight $< | \
        $(CFG_PANDOC) $(HTML_OPTS) --output=$@
 
-DOCS += doc/tutorial-container.html
-doc/tutorial-container.html: tutorial-container.md doc/version_info.html doc/rust.css \
+DOCS += doc/guide-container.html
+doc/guide-container.html: $(S)doc/guide-container.md doc/version_info.html doc/rust.css \
                                doc/favicon.inc
        @$(call E, pandoc: $@)
        $(Q)$(CFG_NODE) $(S)doc/prep.js --highlight $< | \
        $(CFG_PANDOC) $(HTML_OPTS) --output=$@
 
-DOCS += doc/tutorial-ffi.html
-doc/tutorial-ffi.html: tutorial-ffi.md doc/version_info.html doc/rust.css \
+DOCS += doc/guide-ffi.html
+doc/guide-ffi.html: $(S)doc/guide-ffi.md doc/version_info.html doc/rust.css \
                                doc/favicon.inc
        @$(call E, pandoc: $@)
        $(Q)$(CFG_NODE) $(S)doc/prep.js --highlight $< | \
        $(CFG_PANDOC) $(HTML_OPTS) --output=$@
 
-DOCS += doc/tutorial-testing.html
-doc/tutorial-testing.html: tutorial-testing.md doc/version_info.html doc/rust.css \
+DOCS += doc/guide-testing.html
+doc/guide-testing.html: $(S)doc/guide-testing.md doc/version_info.html doc/rust.css \
                                doc/favicon.inc
        @$(call E, pandoc: $@)
        $(Q)$(CFG_NODE) $(S)doc/prep.js --highlight $< | \
        $(CFG_PANDOC) $(HTML_OPTS) --output=$@
 
-DOCS += doc/tutorial-borrowed-ptr.html
-doc/tutorial-borrowed-ptr.html: tutorial-borrowed-ptr.md doc/version_info.html doc/rust.css \
+DOCS += doc/guide-borrowed-ptr.html
+doc/guide-borrowed-ptr.html: $(S)doc/guide-borrowed-ptr.md doc/version_info.html doc/rust.css \
                                doc/favicon.inc
        @$(call E, pandoc: $@)
        $(Q)$(CFG_NODE) $(S)doc/prep.js --highlight $< | \
        $(CFG_PANDOC) $(HTML_OPTS) --output=$@
 
-DOCS += doc/tutorial-tasks.html
-doc/tutorial-tasks.html: tutorial-tasks.md doc/version_info.html doc/rust.css \
+DOCS += doc/guide-tasks.html
+doc/guide-tasks.html: $(S)doc/guide-tasks.md doc/version_info.html doc/rust.css \
                                doc/favicon.inc
        @$(call E, pandoc: $@)
        $(Q)$(CFG_NODE) $(S)doc/prep.js --highlight $< | \
        $(CFG_PANDOC) $(HTML_OPTS) --output=$@
 
-DOCS += doc/tutorial-conditions.html
-doc/tutorial-conditions.html: tutorial-conditions.md doc/version_info.html doc/rust.css \
+DOCS += doc/guide-conditions.html
+doc/guide-conditions.html: $(S)doc/guide-conditions.md doc/version_info.html doc/rust.css \
                                doc/favicon.inc
        @$(call E, pandoc: $@)
        $(Q)$(CFG_NODE) $(S)doc/prep.js --highlight $< | \
        $(CFG_PANDOC) $(HTML_OPTS) --output=$@
 
-DOCS += doc/tutorial-rustpkg.html
-doc/tutorial-rustpkg.html: tutorial-rustpkg.md doc/version_info.html doc/rust.css \
+DOCS += doc/guide-rustpkg.html
+doc/guide-rustpkg.html: $(S)doc/guide-rustpkg.md doc/version_info.html doc/rust.css \
                                doc/favicon.inc
        @$(call E, pandoc: $@)
        $(Q)$(CFG_NODE) $(S)doc/prep.js --highlight $< | \
index 9792ea5cbc9d49ba196dc074804e662933018c7a..6204c536911579a9b03c37a1913f2287802208a9 100644 (file)
@@ -20,8 +20,8 @@ TEST_HOST_CRATES = rustpkg rustc rustdoc syntax
 TEST_CRATES = $(TEST_TARGET_CRATES) $(TEST_HOST_CRATES)
 
 # Markdown files under doc/ that should have their code extracted and run
-DOC_TEST_NAMES = tutorial tutorial-ffi tutorial-macros tutorial-borrowed-ptr \
-                 tutorial-tasks tutorial-conditions tutorial-container rust
+DOC_TEST_NAMES = tutorial guide-ffi guide-macros guide-borrowed-ptr \
+                 guide-tasks guide-conditions guide-container rust
 
 ######################################################################
 # Environment configuration