about summary refs log tree commit diff
path: root/src/doc
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2015-03-25 01:42:42 +0000
committerbors <bors@rust-lang.org>2015-03-25 01:42:42 +0000
commit593db005d4dbce2ff72009c1ba03477b031b2c0f (patch)
treeb585f5625dde7ab0af35fb3dd41a67ba0507f525 /src/doc
parent123a754cb8356d0e78837dd4e58103ad801309ff (diff)
parent3021d4c56422e15331e38f4b7b04c7229e024fda (diff)
downloadrust-593db005d4dbce2ff72009c1ba03477b031b2c0f.tar.gz
rust-593db005d4dbce2ff72009c1ba03477b031b2c0f.zip
Auto merge of #23681 - alexcrichton:rollup, r=alexcrichton
Diffstat (limited to 'src/doc')
-rw-r--r--src/doc/reference.md6
-rw-r--r--src/doc/trpl/SUMMARY.md1
-rw-r--r--src/doc/trpl/associated-types.md202
-rw-r--r--src/doc/trpl/ownership.md4
-rw-r--r--src/doc/trpl/unsafe.md17
5 files changed, 217 insertions, 13 deletions
diff --git a/src/doc/reference.md b/src/doc/reference.md
index 07df3bdad34..32088b2ab67 100644
--- a/src/doc/reference.md
+++ b/src/doc/reference.md
@@ -1265,7 +1265,7 @@ be undesired.
 * Sending signals
 * Accessing/modifying the file system
 * Unsigned integer overflow (well-defined as wrapping)
-* Signed integer overflow (well-defined as two's complement representation
+* Signed integer overflow (well-defined as two’s complement representation
   wrapping)
 
 #### Diverging functions
@@ -2961,10 +2961,10 @@ meaning of the operators on standard types is given here.
   : Exclusive or.
     Calls the `bitxor` method of the `std::ops::BitXor` trait.
 * `<<`
-  : Logical left shift.
+  : Left shift.
     Calls the `shl` method of the `std::ops::Shl` trait.
 * `>>`
-  : Logical right shift.
+  : Right shift.
     Calls the `shr` method of the `std::ops::Shr` trait.
 
 #### Lazy boolean operators
diff --git a/src/doc/trpl/SUMMARY.md b/src/doc/trpl/SUMMARY.md
index 76f8b6c9738..70c74825a07 100644
--- a/src/doc/trpl/SUMMARY.md
+++ b/src/doc/trpl/SUMMARY.md
@@ -22,6 +22,7 @@
     * [More Strings](more-strings.md)
     * [Patterns](patterns.md)
     * [Method Syntax](method-syntax.md)
+    * [Associated Types](associated-types.md)
     * [Closures](closures.md)
     * [Iterators](iterators.md)
     * [Generics](generics.md)
diff --git a/src/doc/trpl/associated-types.md b/src/doc/trpl/associated-types.md
new file mode 100644
index 00000000000..f36c2c56b6a
--- /dev/null
+++ b/src/doc/trpl/associated-types.md
@@ -0,0 +1,202 @@
+% Associated Types
+
+Associated types are a powerful part of Rust's type system. They're related to
+the idea of a 'type family', in other words, grouping multiple types together. That
+description is a bit abstract, so let's dive right into an example. If you want
+to write a `Graph` trait, you have two types to be generic over: the node type
+and the edge type. So you might write a trait, `Graph<N, E>`, that looks like
+this:
+
+```rust
+trait Graph<N, E> {
+    fn has_edge(&self, &N, &N) -> bool;
+    fn edges(&self, &N) -> Vec<E>;
+    // etc
+}
+```
+
+While this sort of works, it ends up being awkward. For example, any function
+that wants to take a `Graph` as a parameter now _also_ needs to be generic over
+the `N`ode and `E`dge types too:
+
+```rust,ignore
+fn distance<N, E, G: Graph<N, E>>(graph: &G, start: &N, end: &N) -> u32 { ... }
+```
+
+Our distance calculation works regardless of our `Edge` type, so the `E` stuff in
+this signature is just a distraction.
+
+What we really want to say is that a certain `E`dge and `N`ode type come together
+to form each kind of `Graph`. We can do that with associated types:
+
+```rust
+trait Graph {
+    type N;
+    type E;
+
+    fn has_edge(&self, &Self::N, &Self::N) -> bool;
+    fn edges(&self, &Self::N) -> Vec<Self::E>;
+    // etc
+}
+```
+
+Now, our clients can be abstract over a given `Graph`:
+
+```rust,ignore
+fn distance<G: Graph>(graph: &G, start: &G::N, end: &G::N) -> uint { ... }
+```
+
+No need to deal with the `E`dge type here!
+
+Let's go over all this in more detail.
+
+## Defining associated types
+
+Let's build that `Graph` trait. Here's the definition:
+
+```rust
+trait Graph {
+    type N;
+    type E;
+
+    fn has_edge(&self, &Self::N, &Self::N) -> bool;
+    fn edges(&self, &Self::N) -> Vec<Self::E>;
+}
+```
+
+Simple enough. Associated types use the `type` keyword, and go inside the body
+of the trait, with the functions.
+
+These `type` declarations can have all the same thing as functions do. For example,
+if we wanted our `N` type to implement `Display`, so we can print the nodes out,
+we could do this:
+
+```rust
+use std::fmt;
+
+trait Graph {
+    type N: fmt::Display;
+    type E;
+
+    fn has_edge(&self, &Self::N, &Self::N) -> bool;
+    fn edges(&self, &Self::N) -> Vec<Self::E>;
+}
+```
+
+## Implementing associated types
+
+Just like any trait, traits that use associated types use the `impl` keyword to
+provide implementations. Here's a simple implementation of Graph:
+
+```rust
+# trait Graph {
+#     type N;
+#     type E;
+#     fn has_edge(&self, &Self::N, &Self::N) -> bool;
+#     fn edges(&self, &Self::N) -> Vec<Self::E>;
+# }
+struct Node;
+
+struct Edge;
+
+struct MyGraph;
+
+impl Graph for MyGraph {
+    type N = Node;
+    type E = Edge;
+
+    fn has_edge(&self, n1: &Node, n2: &Node) -> bool {
+        true
+    }
+
+    fn edges(&self, n: &Node) -> Vec<Edge> {
+        Vec::new()
+    }
+}
+```
+
+This silly implementation always returns `true` and an empty `Vec<Edge>`, but it
+gives you an idea of how to implement this kind of thing. We first need three
+`struct`s, one for the graph, one for the node, and one for the edge. If it made
+more sense to use a different type, that would work as well, we're just going to
+use `struct`s for all three here.
+
+Next is the `impl` line, which is just like implementing any other trait.
+
+From here, we use `=` to define our associated types. The name the trait uses
+goes on the left of the `=`, and the concrete type we're `impl`ementing this
+for goes on the right. Finally, we use the concrete types in our function
+declarations.
+
+## Trait objects with associated types
+
+There’s one more bit of syntax we should talk about: trait objects. If you
+try to create a trait object from an associated type, like this:
+
+```rust,ignore
+# trait Graph {
+#     type N;
+#     type E;
+#     fn has_edge(&self, &Self::N, &Self::N) -> bool;
+#     fn edges(&self, &Self::N) -> Vec<Self::E>;
+# }
+# struct Node;
+# struct Edge;
+# struct MyGraph;
+# impl Graph for MyGraph {
+#     type N = Node;
+#     type E = Edge;
+#     fn has_edge(&self, n1: &Node, n2: &Node) -> bool {
+#         true
+#     }
+#     fn edges(&self, n: &Node) -> Vec<Edge> {
+#         Vec::new()
+#     }
+# }
+let graph = MyGraph;
+let obj = Box::new(graph) as Box<Graph>;
+```
+
+You’ll get two errors:
+
+```text
+error: the value of the associated type `E` (from the trait `main::Graph`) must
+be specified [E0191]
+let obj = Box::new(graph) as Box<Graph>;
+          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+24:44 error: the value of the associated type `N` (from the trait
+`main::Graph`) must be specified [E0191]
+let obj = Box::new(graph) as Box<Graph>;
+          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+```
+
+We can’t create a trait object like this, becuase we don’t know the associated
+types. Instead, we can write this:
+
+```rust
+# trait Graph {
+#     type N;
+#     type E;
+#     fn has_edge(&self, &Self::N, &Self::N) -> bool;
+#     fn edges(&self, &Self::N) -> Vec<Self::E>;
+# }
+# struct Node;
+# struct Edge;
+# struct MyGraph;
+# impl Graph for MyGraph {
+#     type N = Node;
+#     type E = Edge;
+#     fn has_edge(&self, n1: &Node, n2: &Node) -> bool {
+#         true
+#     }
+#     fn edges(&self, n: &Node) -> Vec<Edge> {
+#         Vec::new()
+#     }
+# }
+let graph = MyGraph;
+let obj = Box::new(graph) as Box<Graph<N=Node, E=Edge>>;
+```
+
+The `N=Node` syntax allows us to provide a concrete type, `Node`, for the `N`
+type parameter. Same with `E=Edge`. If we didn’t proide this constraint, we
+couldn’t be sure which `impl` to match this trait object to.
diff --git a/src/doc/trpl/ownership.md b/src/doc/trpl/ownership.md
index 6aced23ede0..b851f19d22d 100644
--- a/src/doc/trpl/ownership.md
+++ b/src/doc/trpl/ownership.md
@@ -513,8 +513,8 @@ Otherwise, it is an error to elide an output lifetime.
 
 ### Examples
 
-Here are some examples of functions with elided lifetimes, and the version of
-what the elided lifetimes are expand to:
+Here are some examples of functions with elided lifetimes.  We've paired each
+example of an elided lifetime with its expanded form.
 
 ```{rust,ignore}
 fn print(s: &str); // elided
diff --git a/src/doc/trpl/unsafe.md b/src/doc/trpl/unsafe.md
index 2116976d55a..dbf0cae6f4b 100644
--- a/src/doc/trpl/unsafe.md
+++ b/src/doc/trpl/unsafe.md
@@ -197,15 +197,16 @@ use std::ptr;
 
 // Define a wrapper around the handle returned by the foreign code.
 // Unique<T> has the same semantics as Box<T>
-pub struct Unique<T> {
+//
+// NB: For simplicity and correctness, we require that T has kind Send
+// (owned boxes relax this restriction).
+pub struct Unique<T: Send> {
     // It contains a single raw, mutable pointer to the object in question.
     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).
 impl<T: Send> Unique<T> {
     pub fn new(value: T) -> Unique<T> {
         unsafe {
@@ -239,11 +240,11 @@ impl<T: Send> Unique<T> {
 // 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 parameterized types, due to
-// bad interaction with managed boxes. (With the Send restriction,
-// we don't have this problem.) Note that the `#[unsafe_destructor]`
-// feature gate is required to use unsafe destructors.
+// NB: This is an unsafe destructor; rustc will not normally allow
+// destructors to be associated with parameterized types (due to
+// historically failing to check them soundly).  Note that the
+// `#[unsafe_destructor]` feature gate is currently required to use
+// unsafe destructors.
 #[unsafe_destructor]
 impl<T: Send> Drop for Unique<T> {
     fn drop(&mut self) {