Skip to content

Commit

Permalink
Auto merge of #25384 - steveklabnik:rollup, r=steveklabnik
Browse files Browse the repository at this point in the history
- Successful merges: #25308, #25360, #25363, #25365, #25371, #25372, #25376, #25379, #25382
- Failed merges:
  • Loading branch information
bors committed May 13, 2015
2 parents 222cd73 + 87c903a commit 5a341ec
Show file tree
Hide file tree
Showing 10 changed files with 252 additions and 31 deletions.
67 changes: 60 additions & 7 deletions src/doc/reference.md
Expand Up @@ -1346,6 +1346,8 @@ vtable when the trait is used as a [trait object](#trait-objects).
Traits are implemented for specific types through separate
[implementations](#implementations).

Consider the following trait:

```
# type Surface = i32;
# type BoundingBox = i32;
Expand All @@ -1360,6 +1362,20 @@ This defines a trait with two methods. All values that have
`draw` and `bounding_box` methods called, using `value.bounding_box()`
[syntax](#method-call-expressions).

Traits can include default implementations of methods, as in:

```
trait Foo {
fn bar(&self);
fn baz(&self) { println!("We called baz."); }
}
```

Here the `baz` method has a default implementation, so types that implement
`Foo` need only implement `bar`. It is also possible for implementing types
to override a method that has a default implementation.

Type parameters can be specified for a trait to make it generic. These appear
after the trait name, using the same syntax used in [generic
functions](#generic-functions).
Expand All @@ -1372,6 +1388,35 @@ trait Seq<T> {
}
```

It is also possible to define associated types for a trait. Consider the
following example of a `Container` trait. Notice how the type is available
for use in the method signatures:

```
trait Container {
type E;
fn empty() -> Self;
fn insert(&mut self, Self::E);
}
```

In order for a type to implement this trait, it must not only provide
implementations for every method, but it must specify the type `E`. Here's
an implementation of `Container` for the standard library type `Vec`:

```
# trait Container {
# type E;
# fn empty() -> Self;
# fn insert(&mut self, Self::E);
# }
impl<T> Container for Vec<T> {
type E = T;
fn empty() -> Vec<T> { Vec::new() }
fn insert(&mut self, x: T) { self.push(x); }
}
```

Generic functions may use traits as _bounds_ on their type parameters. This
will have two effects: only types that have the trait may instantiate the
parameter, and within the generic function, the methods of the trait can be
Expand Down Expand Up @@ -3470,13 +3515,21 @@ more of the closure traits:

### Trait objects

Every trait item (see [traits](#traits)) defines a type with the same name as
the trait. This type is called the _trait object_ of the trait. Trait objects
permit "late binding" of methods, dispatched using _virtual method tables_
("vtables"). Whereas most calls to trait methods are "early bound" (statically
resolved) to specific implementations at compile time, a call to a method on an
trait objects is only resolved to a vtable entry at compile time. The actual
implementation for each vtable entry can vary on an object-by-object basis.
In Rust, a type like `&SomeTrait` or `Box<SomeTrait>` is called a _trait object_.
Each instance of a trait object includes:

- a pointer to an instance of a type `T` that implements `SomeTrait`
- a _virtual method table_, often just called a _vtable_, which contains, for
each method of `SomeTrait` that `T` implements, a pointer to `T`'s
implementation (i.e. a function pointer).

The purpose of trait objects is to permit "late binding" of methods. A call to
a method on a trait object is only resolved to a vtable entry at compile time.
The actual implementation for each vtable entry can vary on an object-by-object
basis.

Note that for a trait object to be instantiated, the trait must be
_object-safe_. Object safety rules are defined in [RFC 255][rfc255].

Given a pointer-typed expression `E` of type `&T` or `Box<T>`, where `T`
implements trait `R`, casting `E` to the corresponding pointer type `&R` or
Expand Down
2 changes: 1 addition & 1 deletion src/doc/trpl/README.md
Expand Up @@ -175,7 +175,7 @@ data, we call the `clone()` method. In this example, `y` is no longer a referenc
to the vector stored in `x`, but a copy of its first element, `"Hello"`. Now
that we don’t have a reference, our `push()` works just fine.

[move]: move-semantics.html
[move]: ownership.html#move-semantics

If we truly want a reference, we need the other option: ensure that our reference
goes out of scope before we try to do the mutation. That looks like this:
Expand Down
2 changes: 1 addition & 1 deletion src/doc/trpl/dining-philosophers.md
Expand Up @@ -450,7 +450,7 @@ which blocks execution until the thread has completed execution. This ensures
that the threads complete their work before the program exits.

If you run this program, you’ll see that the philosophers eat out of order!
We have mult-threading!
We have multi-threading!

```text
Gilles Deleuze is eating.
Expand Down
2 changes: 2 additions & 0 deletions src/doc/trpl/error-handling.md
Expand Up @@ -181,6 +181,8 @@ match version {
This function makes use of an enum, `ParseError`, to enumerate the various
errors that can occur.

The [`Debug`](../std/fmt/trait.Debug.html) trait is what lets us print the enum value using the `{:?}` format operation.

# Non-recoverable errors with `panic!`

In the case of an error that is unexpected and not recoverable, the `panic!`
Expand Down
2 changes: 1 addition & 1 deletion src/doc/trpl/the-stack-and-the-heap.md
Expand Up @@ -266,7 +266,7 @@ Rust programs use [jemalloc][jemalloc] for this purpose.
Anyway, back to our example. Since this memory is on the heap, it can stay
alive longer than the function which allocates the box. In this case, however,
it doesn’t.[^moving] When the function is over, we need to free the stack frame
for `main()`. `Box<T>`, though, has a trick up its sleve: [Drop][drop]. The
for `main()`. `Box<T>`, though, has a trick up its sleeve: [Drop][drop]. The
implementation of `Drop` for `Box` deallocates the memory that was allocated
when it was created. Great! So when `x` goes away, it first frees the memory
allocated on the heap:
Expand Down
22 changes: 12 additions & 10 deletions src/libcollections/vec.rs
Expand Up @@ -18,39 +18,41 @@
//! You can explicitly create a `Vec<T>` with `new()`:
//!
//! ```
//! let xs: Vec<i32> = Vec::new();
//! let v: Vec<i32> = Vec::new();
//! ```
//!
//! ...or by using the `vec!` macro:
//!
//! ```
//! let ys: Vec<i32> = vec![];
//! let v: Vec<i32> = vec![];
//!
//! let zs = vec![1i32, 2, 3, 4, 5];
//! let v = vec![1, 2, 3, 4, 5];
//!
//! let v = vec![0; 10]; // ten zeroes
//! ```
//!
//! You can `push` values onto the end of a vector (which will grow the vector as needed):
//!
//! ```
//! let mut xs = vec![1i32, 2];
//! let mut v = vec![1, 2];
//!
//! xs.push(3);
//! v.push(3);
//! ```
//!
//! Popping values works in much the same way:
//!
//! ```
//! let mut xs = vec![1i32, 2];
//! let mut v = vec![1, 2];
//!
//! let two = xs.pop();
//! let two = v.pop();
//! ```
//!
//! Vectors also support indexing (through the `Index` and `IndexMut` traits):
//!
//! ```
//! let mut xs = vec![1i32, 2, 3];
//! let three = xs[2];
//! xs[1] = xs[1] + 5;
//! let mut v = vec![1, 2, 3];
//! let three = v[2];
//! v[1] = v[1] + 5;
//! ```

#![stable(feature = "rust1", since = "1.0.0")]
Expand Down
2 changes: 1 addition & 1 deletion src/libcore/macros.rs
Expand Up @@ -167,7 +167,7 @@ macro_rules! try {
})
}

/// Use the `format!` syntax to write data into a buffer of type `&mut Writer`.
/// Use the `format!` syntax to write data into a buffer of type `&mut Write`.
/// See `std::fmt` for more information.
///
/// # Examples
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/diagnostics.rs
Expand Up @@ -427,8 +427,8 @@ be taken.

E0271: r##"
This is because of a type mismatch between the associated type of some
trait (e.g. T::Bar, where T implements trait Quux { type Bar; })
and another type U that is required to be equal to T::Bar, but is not.
trait (e.g. `T::Bar`, where `T` implements `trait Quux { type Bar; }`)
and another type `U` that is required to be equal to `T::Bar`, but is not.
Examples follow.
Here is a basic example:
Expand Down
5 changes: 5 additions & 0 deletions src/librustc_resolve/diagnostics.rs
Expand Up @@ -20,6 +20,7 @@ Imports (`use` statements) are not allowed after non-item statements, such as
variable declarations and expression statements.
Here is an example that demonstrates the error:
```
fn f() {
// Variable declaration before import
Expand All @@ -33,6 +34,7 @@ The solution is to declare the imports at the top of the block, function, or
file.
Here is the previous example again, with the correct order:
```
fn f() {
use std::io::Read;
Expand All @@ -52,6 +54,7 @@ The name chosen for an external crate conflicts with another external crate that
has been imported into the current module.
Wrong example:
```
extern crate a;
extern crate crate_a as a;
Expand All @@ -61,6 +64,7 @@ The solution is to choose a different name that doesn't conflict with any
external crate imported into the current module.
Correct example:
```
extern crate a;
extern crate crate_a as other_name;
Expand All @@ -71,6 +75,7 @@ E0260: r##"
The name for an item declaration conflicts with an external crate's name.
For instance,
```
extern crate abc;
Expand Down

0 comments on commit 5a341ec

Please sign in to comment.