about summary refs log tree commit diff
path: root/src/doc
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2015-02-10 19:52:04 +0000
committerbors <bors@rust-lang.org>2015-02-10 19:52:04 +0000
commitbc87efef2cceaec99d30e809cac2b8d22b9e25fc (patch)
tree1f59e50bc58a426615cc15594cade8b69f24bdbf /src/doc
parent88d8ba5ab3b1d22288b021708c3d87464e43b880 (diff)
parent3e10785e21b731d536cf9ad9b911e8261862bde7 (diff)
downloadrust-bc87efef2cceaec99d30e809cac2b8d22b9e25fc.tar.gz
rust-bc87efef2cceaec99d30e809cac2b8d22b9e25fc.zip
Auto merge of #22153 - alexcrichton:rollup, r=alexcrichton
Diffstat (limited to 'src/doc')
-rw-r--r--src/doc/grammar.md2
-rw-r--r--src/doc/index.md3
-rw-r--r--src/doc/reference.md22
-rw-r--r--src/doc/rust.css2
-rw-r--r--src/doc/trpl/SUMMARY.md1
-rw-r--r--src/doc/trpl/closures.md20
-rw-r--r--src/doc/trpl/compound-data-types.md14
-rw-r--r--src/doc/trpl/static-and-dynamic-dispatch.md286
-rw-r--r--src/doc/trpl/traits.md47
9 files changed, 327 insertions, 70 deletions
diff --git a/src/doc/grammar.md b/src/doc/grammar.md
index 59a1c8f828b..b4e023c2039 100644
--- a/src/doc/grammar.md
+++ b/src/doc/grammar.md
@@ -157,7 +157,7 @@ token : simple_token | ident | literal | symbol | whitespace token ;
 
 |          |          |          |          |        |
 |----------|----------|----------|----------|--------|
-| abstract | alignof  | as       | be       | box    |
+| abstract | alignof  | as       | become   | box    |
 | break    | const    | continue | crate    | do     |
 | else     | enum     | extern   | false    | final  |
 | fn       | for      | if       | impl     | in     |
diff --git a/src/doc/index.md b/src/doc/index.md
index 252a3125ebd..a4f79412220 100644
--- a/src/doc/index.md
+++ b/src/doc/index.md
@@ -59,8 +59,7 @@ tools we have are really nice.
 [Cargo](http://crates.io) is Rust's package manager, and its website contains
 lots of good documentation.
 
-[The `rustdoc` manual](rustdoc.html) contains information about Rust's
-documentation tool.
+[`rustdoc`](book/documentation.html) is used to generate documentation for Rust code.
 
 # FAQs
 
diff --git a/src/doc/reference.md b/src/doc/reference.md
index 999efc95c0e..d50c0d6582b 100644
--- a/src/doc/reference.md
+++ b/src/doc/reference.md
@@ -189,7 +189,7 @@ grammar as double-quoted strings. Other tokens have exact rules given.
 
 |          |          |          |          |         |
 |----------|----------|----------|----------|---------|
-| abstract | alignof  | as       | be       | box     |
+| abstract | alignof  | as       | become   | box     |
 | break    | const    | continue | crate    | do      |
 | else     | enum     | extern   | false    | final   |
 | fn       | for      | if       | impl     | in      |
@@ -381,11 +381,13 @@ character (`\`), or a single _escape_. It is equivalent to a `u8` unsigned
 
 ##### Byte string literals
 
-A _byte string literal_ is a sequence of ASCII characters and _escapes_
-enclosed within two `U+0022` (double-quote) characters, with the exception of
-`U+0022` itself, which must be _escaped_ by a preceding `U+005C` character
-(`\`), or a _raw byte string literal_. It is equivalent to a `&'static [u8]`
-borrowed array of unsigned 8-bit integers.
+A non-raw _byte string literal_ is a sequence of ASCII characters and _escapes_,
+preceded by the characters `U+0062` (`b`) and `U+0022` (double-quote), and
+followed by the character `U+0022`. If the character `U+0022` is present within
+the literal, it must be _escaped_ by a preceding `U+005C` (`\`) character.
+Alternatively, a byte string literal can be a _raw byte string literal_, defined
+below. A byte string literal is equivalent to a `&'static [u8]` borrowed array
+of unsigned 8-bit integers.
 
 Some additional _escapes_ are available in either byte or non-raw byte string
 literals. An escape starts with a `U+005C` (`\`) and continues with one of the
@@ -1253,9 +1255,7 @@ fn my_err(s: &str) -> ! {
 We call such functions "diverging" because they never return a value to the
 caller. Every control path in a diverging function must end with a `panic!()` or
 a call to another diverging function on every control path. The `!` annotation
-does *not* denote a type. Rather, the result type of a diverging function is a
-special type called ⊥ ("bottom") that unifies with any type. Rust has no
-syntax for ⊥.
+does *not* denote a type.
 
 It might be necessary to declare a diverging function because as mentioned
 previously, the typechecker checks that every control path in a function ends
@@ -2354,8 +2354,8 @@ Supported traits for `derive` are:
 * `FromPrimitive`, to create an instance from a numeric primitive.
 * `Hash`, to iterate over the bytes in a data type.
 * `Rand`, to create a random instance of a data type.
-* `Show`, to format a value using the `{}` formatter.
-* `Zero`, to create a zero instance of a numeric data type.
+* `Debug`, to format a value using the `{:?}` formatter.
+* `Copy`, for "Plain Old Data" types which can be copied by simply moving bits.
 
 ### Compiler Features
 
diff --git a/src/doc/rust.css b/src/doc/rust.css
index 3f59f12e74c..c2a25cd7a58 100644
--- a/src/doc/rust.css
+++ b/src/doc/rust.css
@@ -58,7 +58,7 @@
 body {
     margin: 0 auto;
     padding: 0 15px;
-    font-family: "Source Serif Pro", "Helvetica Neue", Helvetica, Arial, sans-serif;
+    font-family: "Source Serif Pro", Georgia, Times, "Times New Roman", serif;
     font-size: 18px;
     color: #333;
     line-height: 1.428571429;
diff --git a/src/doc/trpl/SUMMARY.md b/src/doc/trpl/SUMMARY.md
index 9d65f30e723..bfc1247dc3b 100644
--- a/src/doc/trpl/SUMMARY.md
+++ b/src/doc/trpl/SUMMARY.md
@@ -27,6 +27,7 @@
     * [Iterators](iterators.md)
     * [Generics](generics.md)
     * [Traits](traits.md)
+    * [Static and Dynamic Dispatch](static-and-dynamic-dispatch.md)
     * [Concurrency](concurrency.md)
     * [Error Handling](error-handling.md)
     * [Documentation](documentation.md)
diff --git a/src/doc/trpl/closures.md b/src/doc/trpl/closures.md
index bfb1494efc7..8cc6be7387c 100644
--- a/src/doc/trpl/closures.md
+++ b/src/doc/trpl/closures.md
@@ -9,7 +9,7 @@ arguments, really powerful things are possible.
 Let's make a closure:
 
 ```{rust}
-let add_one = |&: x| { 1 + x };
+let add_one = |x| { 1 + x };
 
 println!("The sum of 5 plus 1 is {}.", add_one(5));
 ```
@@ -21,8 +21,8 @@ binding name and two parentheses, just like we would for a named function.
 Let's compare syntax. The two are pretty close:
 
 ```{rust}
-let add_one = |&: x: i32| -> i32 { 1 + x };
-fn  add_one      (x: i32) -> i32 { 1 + x }
+let add_one = |x: i32| -> i32 { 1 + x };
+fn  add_one   (x: i32) -> i32 { 1 + x }
 ```
 
 As you may have noticed, closures infer their argument and return types, so you
@@ -37,7 +37,7 @@ this:
 fn main() {
     let x: i32 = 5;
 
-    let printer = |&:| { println!("x is: {}", x); };
+    let printer = || { println!("x is: {}", x); };
 
     printer(); // prints "x is: 5"
 }
@@ -53,7 +53,7 @@ defined. The closure borrows any variables it uses, so this will error:
 fn main() {
     let mut x: i32 = 5;
 
-    let printer = |&:| { println!("x is: {}", x); };
+    let printer = || { println!("x is: {}", x); };
 
     x = 6; // error: cannot assign to `x` because it is borrowed
 }
@@ -80,7 +80,7 @@ fn twice<F: Fn(i32) -> i32>(x: i32, f: F) -> i32 {
 }
 
 fn main() {
-    let square = |&: x: i32| { x * x };
+    let square = |x: i32| { x * x };
 
     twice(5, square); // evaluates to 50
 }
@@ -89,7 +89,7 @@ fn main() {
 Let's break the example down, starting with `main`:
 
 ```{rust}
-let square = |&: x: i32| { x * x };
+let square = |x: i32| { x * x };
 ```
 
 We've seen this before. We make a closure that takes an integer, and returns
@@ -97,7 +97,7 @@ its square.
 
 ```{rust}
 # fn twice<F: Fn(i32) -> i32>(x: i32, f: F) -> i32 { f(x) + f(x) }
-# let square = |&: x: i32| { x * x };
+# let square = |x: i32| { x * x };
 twice(5, square); // evaluates to 50
 ```
 
@@ -184,8 +184,8 @@ fn compose<F, G>(x: i32, f: F, g: G) -> i32
 
 fn main() {
     compose(5,
-            |&: n: i32| { n + 42 },
-            |&: n: i32| { n * 2 }); // evaluates to 94
+            |n: i32| { n + 42 },
+            |n: i32| { n * 2 }); // evaluates to 94
 }
 ```
 
diff --git a/src/doc/trpl/compound-data-types.md b/src/doc/trpl/compound-data-types.md
index 8b99278acb1..51a4edbdac8 100644
--- a/src/doc/trpl/compound-data-types.md
+++ b/src/doc/trpl/compound-data-types.md
@@ -72,6 +72,20 @@ if x == y {
 
 This will print `no`, because some of the values aren't equal.
 
+Note that the order of the values is considered when checking for equality,
+so the following example will also print `no`.
+
+```rust
+let x = (1, 2, 3);
+let y = (2, 1, 3);
+
+if x == y {
+    println!("yes");
+} else {
+    println!("no");
+}
+```
+
 One other use of tuples is to return multiple values from a function:
 
 ```rust
diff --git a/src/doc/trpl/static-and-dynamic-dispatch.md b/src/doc/trpl/static-and-dynamic-dispatch.md
new file mode 100644
index 00000000000..9421dac7bf6
--- /dev/null
+++ b/src/doc/trpl/static-and-dynamic-dispatch.md
@@ -0,0 +1,286 @@
+% Static and Dynamic Dispatch
+
+When code involves polymorphism, there needs to be a mechanism to determine
+which specific version is actually run. This is called 'dispatch.' There are
+two major forms of dispatch: static dispatch and dynamic dispatch. While Rust
+favors static dispatch, it also supports dynamic dispatch through a mechanism
+called 'trait objects.'
+
+## Background
+
+For the rest of this chapter, we'll need a trait and some implementations.
+Let's make a simple one, `Foo`. It has one method that is expected to return a
+`String`.
+
+```rust
+trait Foo {
+    fn method(&self) -> String;
+}
+```
+
+We'll also implement this trait for `u8` and `String`:
+
+```rust
+# trait Foo { fn method(&self) -> String; }
+impl Foo for u8 {
+    fn method(&self) -> String { format!("u8: {}", *self) }
+}
+
+impl Foo for String {
+    fn method(&self) -> String { format!("string: {}", *self) }
+}
+```
+
+
+## Static dispatch
+
+We can use this trait to perform static dispatch with trait bounds:
+
+```rust
+# trait Foo { fn method(&self) -> String; }
+# impl Foo for u8 { fn method(&self) -> String { format!("u8: {}", *self) } }
+# impl Foo for String { fn method(&self) -> String { format!("string: {}", *self) } }
+fn do_something<T: Foo>(x: T) {
+    x.method();
+}
+
+fn main() {
+    let x = 5u8;
+    let y = "Hello".to_string();
+
+    do_something(x);
+    do_something(y);
+}
+```
+
+Rust uses 'monomorphization' to perform static dispatch here. This means that
+Rust will create a special version of `do_something()` for both `u8` and
+`String`, and then replace the call sites with calls to these specialized
+functions. In other words, Rust generates something like this:
+
+```rust
+# trait Foo { fn method(&self) -> String; }
+# impl Foo for u8 { fn method(&self) -> String { format!("u8: {}", *self) } }
+# impl Foo for String { fn method(&self) -> String { format!("string: {}", *self) } }
+fn do_something_u8(x: u8) {
+    x.method();
+}
+
+fn do_something_string(x: String) {
+    x.method();
+}
+
+fn main() {
+    let x = 5u8;
+    let y = "Hello".to_string();
+
+    do_something_u8(x);
+    do_something_string(y);
+}
+```
+
+This has some upsides: static dispatching of any method calls, allowing for
+inlining and hence usually higher performance. It also has some downsides:
+causing code bloat due to many copies of the same function existing in the
+binary, one for each type.
+
+Furthermore, compilers aren’t perfect and may “optimise” code to become slower.
+For example, functions inlined too eagerly will bloat the instruction cache
+(cache rules everything around us). This is part of the reason that `#[inline]`
+and `#[inline(always)]` should be used carefully, and one reason why using a
+dynamic dispatch is sometimes more efficient.
+
+However, the common case is that it is more efficient to use static dispatch,
+and one can always have a thin statically-dispatched wrapper function that does
+a dynamic, but not vice versa, meaning static calls are more flexible. The
+standard library tries to be statically dispatched where possible for this
+reason. 
+
+## Dynamic dispatch
+
+Rust provides dynamic dispatch through a feature called 'trait objects.' Trait
+objects, like `&Foo` or `Box<Foo>`, are normal values that store a value of
+*any* type that implements the given trait, where the precise type can only be
+known at runtime. The methods of the trait can be called on a trait object via
+a special record of function pointers (created and managed by the compiler).
+
+A function that takes a trait object is not specialised to each of the types
+that implements `Foo`: only one copy is generated, often (but not always)
+resulting in less code bloat. However, this comes at the cost of requiring
+slower virtual function calls, and effectively inhibiting any chance of
+inlining and related optimisations from occurring.
+
+Trait objects are both simple and complicated: their core representation and
+layout is quite straight-forward, but there are some curly error messages and
+surprising behaviours to discover.
+
+### Obtaining a trait object
+
+There's two similar ways to get a trait object value: casts and coercions. If
+`T` is a type that implements a trait `Foo` (e.g. `u8` for the `Foo` above),
+then the two ways to get a `Foo` trait object out of a pointer to `T` look
+like:
+
+```{rust,ignore}
+let ref_to_t: &T = ...;
+
+// `as` keyword for casting
+let cast = ref_to_t as &Foo;
+
+// using a `&T` in a place that has a known type of `&Foo` will implicitly coerce:
+let coerce: &Foo = ref_to_t;
+
+fn also_coerce(_unused: &Foo) {}
+also_coerce(ref_to_t);
+```
+
+These trait object coercions and casts also work for pointers like `&mut T` to
+`&mut Foo` and `Box<T>` to `Box<Foo>`, but that's all at the moment. Coercions
+and casts are identical.
+
+This operation can be seen as "erasing" the compiler's knowledge about the
+specific type of the pointer, and hence trait objects are sometimes referred to
+"type erasure".
+
+### Representation
+
+Let's start simple, with the runtime representation of a trait object. The
+`std::raw` module contains structs with layouts that are the same as the
+complicated build-in types, [including trait objects][stdraw]:
+
+```rust
+# mod foo {
+pub struct TraitObject {
+    pub data: *mut (),
+    pub vtable: *mut (),
+}
+# }
+```
+
+[stdraw]: ../std/raw/struct.TraitObject.html
+
+That is, a trait object like `&Foo` consists of a "data" pointer and a "vtable"
+pointer.
+
+The data pointer addresses the data (of some unknown type `T`) that the trait
+object is storing, and the vtable pointer points to the vtable ("virtual method
+table") corresponding to the implementation of `Foo` for `T`.
+
+
+A vtable is essentially a struct of function pointers, pointing to the concrete
+piece of machine code for each method in the implementation. A method call like
+`trait_object.method()` will retrieve the correct pointer out of the vtable and
+then do a dynamic call of it. For example:
+
+```{rust,ignore}
+struct FooVtable {
+    destructor: fn(*mut ()),
+    size: usize,
+    align: usize,
+    method: fn(*const ()) -> String,
+}
+
+// u8:
+
+fn call_method_on_u8(x: *const ()) -> String {
+    // the compiler guarantees that this function is only called
+    // with `x` pointing to a u8
+    let byte: &u8 = unsafe { &*(x as *const u8) };
+
+    byte.method()
+}
+
+static Foo_for_u8_vtable: FooVtable = FooVtable {
+    destructor: /* compiler magic */,
+    size: 1,
+    align: 1,
+
+    // cast to a function pointer
+    method: call_method_on_u8 as fn(*const ()) -> String,
+};
+
+
+// String:
+
+fn call_method_on_String(x: *const ()) -> String {
+    // the compiler guarantees that this function is only called
+    // with `x` pointing to a String
+    let string: &String = unsafe { &*(x as *const String) };
+
+    string.method()
+}
+
+static Foo_for_String_vtable: FooVtable = FooVtable {
+    destructor: /* compiler magic */,
+    // values for a 64-bit computer, halve them for 32-bit ones
+    size: 24,
+    align: 8,
+
+    method: call_method_on_String as fn(*const ()) -> String,
+};
+```
+
+The `destructor` field in each vtable points to a function that will clean up
+any resources of the vtable's type, for `u8` it is trivial, but for `String` it
+will free the memory. This is necessary for owning trait objects like
+`Box<Foo>`, which need to clean-up both the `Box` allocation and as well as the
+internal type when they go out of scope. The `size` and `align` fields store
+the size of the erased type, and its alignment requirements; these are
+essentially unused at the moment since the information is embedded in the
+destructor, but will be used in future, as trait objects are progressively made
+more flexible.
+
+Suppose we've got some values that implement `Foo`, the explicit form of
+construction and use of `Foo` trait objects might look a bit like (ignoring the
+type mismatches: they're all just pointers anyway):
+
+```{rust,ignore}
+let a: String = "foo".to_string();
+let x: u8 = 1;
+
+// let b: &Foo = &a;
+let b = TraitObject {
+    // store the data
+    data: &a,
+    // store the methods
+    vtable: &Foo_for_String_vtable
+};
+
+// let y: &Foo = x;
+let y = TraitObject {
+    // store the data
+    data: &x,
+    // store the methods
+    vtable: &Foo_for_u8_vtable
+};
+
+// b.method();
+(b.vtable.method)(b.data);
+
+// y.method();
+(y.vtable.method)(y.data);
+```
+
+If `b` or `y` were owning trait objects (`Box<Foo>`), there would be a
+`(b.vtable.destructor)(b.data)` (respectively `y`) call when they went out of
+scope.
+
+### Why pointers?
+
+The use of language like "fat pointer" implies that a trait object is
+always a pointer of some form, but why?
+
+Rust does not put things behind a pointer by default, unlike many managed
+languages, so types can have different sizes. Knowing the size of the value at
+compile time is important for things like passing it as an argument to a
+function, moving it about on the stack and allocating (and deallocating) space
+on the heap to store it.
+
+For `Foo`, we would need to have a value that could be at least either a
+`String` (24 bytes) or a `u8` (1 byte), as well as any other type for which
+dependent crates may implement `Foo` (any number of bytes at all). There's no
+way to guarantee that this last point can work if the values are stored without
+a pointer, because those other types can be arbitrarily large.
+
+Putting the value behind a pointer means the size of the value is not relevant
+when we are tossing a trait object around, only the size of the pointer itself.
diff --git a/src/doc/trpl/traits.md b/src/doc/trpl/traits.md
index d12480d7dd9..e091878cf86 100644
--- a/src/doc/trpl/traits.md
+++ b/src/doc/trpl/traits.md
@@ -270,51 +270,8 @@ not, because both the trait and the type aren't in our crate.
 
 One last thing about traits: generic functions with a trait bound use
 *monomorphization* (*mono*: one, *morph*: form), so they are statically
-dispatched. What's that mean? Well, let's take a look at `print_area` again:
-
-```{rust,ignore}
-fn print_area<T: HasArea>(shape: T) {
-    println!("This shape has an area of {}", shape.area());
-}
-
-fn main() {
-    let c = Circle { ... };
-
-    let s = Square { ... };
-
-    print_area(c);
-    print_area(s);
-}
-```
-
-When we use this trait with `Circle` and `Square`, Rust ends up generating
-two different functions with the concrete type, and replacing the call sites with
-calls to the concrete implementations. In other words, you get something like
-this:
-
-```{rust,ignore}
-fn __print_area_circle(shape: Circle) {
-    println!("This shape has an area of {}", shape.area());
-}
-
-fn __print_area_square(shape: Square) {
-    println!("This shape has an area of {}", shape.area());
-}
-
-fn main() {
-    let c = Circle { ... };
-
-    let s = Square { ... };
-
-    __print_area_circle(c);
-    __print_area_square(s);
-}
-```
-
-The names don't actually change to this, it's just for illustration. But
-as you can see, there's no overhead of deciding which version to call here,
-hence *statically dispatched*. The downside is that we have two copies of
-the same function, so our binary is a little bit larger.
+dispatched. What's that mean? Check out the chapter on [static and dynamic
+dispatch](static-and-dynamic-dispatch.html) for more.
 
 ## Our `inverse` Example