Skip to content

Commit

Permalink
Auto merge of #23681 - alexcrichton:rollup, r=alexcrichton
Browse files Browse the repository at this point in the history
  • Loading branch information
bors committed Mar 25, 2015
2 parents 123a754 + 3021d4c commit 593db00
Show file tree
Hide file tree
Showing 171 changed files with 2,212 additions and 1,034 deletions.
6 changes: 3 additions & 3 deletions src/doc/reference.md
Expand Up @@ -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 twos complement representation
wrapping)

#### Diverging functions
Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions src/doc/trpl/SUMMARY.md
Expand Up @@ -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)
Expand Down
202 changes: 202 additions & 0 deletions 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.
4 changes: 2 additions & 2 deletions src/doc/trpl/ownership.md
Expand Up @@ -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
Expand Down
17 changes: 9 additions & 8 deletions src/doc/trpl/unsafe.md
Expand Up @@ -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 {
Expand Down Expand Up @@ -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) {
Expand Down
10 changes: 10 additions & 0 deletions src/etc/libc.c
Expand Up @@ -165,6 +165,16 @@ void posix88_consts() {
put_const(S_IWUSR, int);
put_const(S_IRUSR, int);

put_const(S_IRWXG, int);
put_const(S_IXGRP, int);
put_const(S_IWGRP, int);
put_const(S_IRGRP, int);

put_const(S_IRWXO, int);
put_const(S_IXOTH, int);
put_const(S_IWOTH, int);
put_const(S_IROTH, int);

#ifdef F_OK
put_const(F_OK, int);
#endif
Expand Down
6 changes: 3 additions & 3 deletions src/liballoc/arc.rs
Expand Up @@ -321,7 +321,7 @@ impl<T: Send + Sync + Clone> Arc<T> {

#[unsafe_destructor]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Sync + Send> Drop for Arc<T> {
impl<T> Drop for Arc<T> {
/// Drops the `Arc<T>`.
///
/// This will decrement the strong reference count. If the strong reference
Expand Down Expand Up @@ -388,7 +388,7 @@ impl<T: Sync + Send> Drop for Arc<T> {

#[unstable(feature = "alloc",
reason = "Weak pointers may not belong in this module.")]
impl<T: Sync + Send> Weak<T> {
impl<T> Weak<T> {
/// Upgrades a weak reference to a strong reference.
///
/// Upgrades the `Weak<T>` reference to an `Arc<T>`, if possible.
Expand Down Expand Up @@ -454,7 +454,7 @@ impl<T: Sync + Send> Clone for Weak<T> {

#[unsafe_destructor]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Sync + Send> Drop for Weak<T> {
impl<T> Drop for Weak<T> {
/// Drops the `Weak<T>`.
///
/// This will decrement the weak reference count.
Expand Down
3 changes: 2 additions & 1 deletion src/libarena/lib.rs
Expand Up @@ -429,7 +429,8 @@ impl<T> TypedArenaChunk<T> {
// Destroy the next chunk.
let next = self.next;
let size = calculate_size::<T>(self.capacity);
deallocate(self as *mut TypedArenaChunk<T> as *mut u8, size,
let self_ptr: *mut TypedArenaChunk<T> = self;
deallocate(self_ptr as *mut u8, size,
mem::min_align_of::<TypedArenaChunk<T>>());
if !next.is_null() {
let capacity = (*next).capacity;
Expand Down
2 changes: 2 additions & 0 deletions src/libcollections/lib.rs
Expand Up @@ -24,6 +24,8 @@
html_playground_url = "http://play.rust-lang.org/")]
#![doc(test(no_crate_inject))]

#![allow(trivial_casts)]
#![allow(trivial_numeric_casts)]
#![feature(alloc)]
#![feature(box_syntax)]
#![feature(box_patterns)]
Expand Down
4 changes: 2 additions & 2 deletions src/libcollections/vec.rs
Expand Up @@ -1199,8 +1199,8 @@ impl<T: PartialEq> Vec<T> {

// Avoid bounds checks by using unsafe pointers.
let p = self.as_mut_ptr();
let mut r = 1;
let mut w = 1;
let mut r: usize = 1;
let mut w: usize = 1;

while r < ln {
let p_r = p.offset(r as isize);
Expand Down
10 changes: 8 additions & 2 deletions src/libcollectionstest/btree/set.rs
Expand Up @@ -43,15 +43,21 @@ struct Counter<'a, 'b> {
}

impl<'a, 'b, 'c> FnMut<(&'c i32,)> for Counter<'a, 'b> {
type Output = bool;

extern "rust-call" fn call_mut(&mut self, (&x,): (&'c i32,)) -> bool {
assert_eq!(x, self.expected[*self.i]);
*self.i += 1;
true
}
}

impl<'a, 'b, 'c> FnOnce<(&'c i32,)> for Counter<'a, 'b> {
type Output = bool;

extern "rust-call" fn call_once(mut self, args: (&'c i32,)) -> bool {
self.call_mut(args)
}
}

fn check<F>(a: &[i32], b: &[i32], expected: &[i32], f: F) where
// FIXME Replace Counter with `Box<FnMut(_) -> _>`
F: FnOnce(&BTreeSet<i32>, &BTreeSet<i32>, Counter) -> bool,
Expand Down
8 changes: 4 additions & 4 deletions src/libcore/any.rs
Expand Up @@ -82,11 +82,11 @@ use marker::Sized;
// Any trait
///////////////////////////////////////////////////////////////////////////////

/// The `Any` trait is implemented by all `'static` types, and can be used for
/// dynamic typing
/// A type to emulate dynamic typing. See the [module-level documentation][mod] for more details.
///
/// Every type with no non-`'static` references implements `Any`, so `Any` can
/// be used as a trait object to emulate the effects dynamic typing.
/// Every type with no non-`'static` references implements `Any`.
///
/// [mod]: ../index.html
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Any: 'static {
/// Get the `TypeId` of `self`
Expand Down

0 comments on commit 593db00

Please sign in to comment.