Skip to content

Commit

Permalink
Reogranise the traits section
Browse files Browse the repository at this point in the history
  • Loading branch information
matthewjasper committed Aug 9, 2017
1 parent fa836c6 commit 7c8ff20
Showing 1 changed file with 131 additions and 107 deletions.
238 changes: 131 additions & 107 deletions src/items.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,9 @@ some other [path]. Usually a `use` declaration is used to shorten the path
required to refer to a module item. These declarations may appear in [modules]
and [blocks], usually at the top.

[path]: paths.html [modules]: #modules [blocks]:
../grammar.html#block-expressions
[path]: paths.html
[modules]: #modules
[blocks]: expressions.html#block-expressions

> **Note**: Unlike in many languages, `use` declarations in Rust do *not*
> declare linkage dependency with external crates. Rather, [`extern crate`
Expand Down Expand Up @@ -475,7 +476,8 @@ let px: i32 = p.x;
A _tuple struct_ is a nominal [tuple type], also defined with the keyword
`struct`. For example:

[struct type]: types.html#struct-types [tuple type]: types.html#tuple-types
[struct type]: types.html#struct-types
[tuple type]: types.html#tuple-types

```rust
struct Point(i32, i32);
Expand Down Expand Up @@ -871,25 +873,23 @@ const RESOLVED_STATIC: Fn(&Foo, &Bar) -> &Baz = ..
A _trait_ describes an abstract interface that types can implement. This
interface consists of associated items, which come in three varieties:

- functions
- [functions](#associated-functions-and-methods)
- [types](#associated-types)
- [constants](#associated-constants)

Associated functions whose first parameter is named `self` are called methods
and may be invoked using `.` notation (e.g., `x.foo()`).

All traits define an implicit type parameter `Self` that refers to "the type
that is implementing this interface". Traits may also contain additional type
parameters. These type parameters (including `Self`) may be constrained by
other traits and so forth as usual.

Trait bounds on `Self` are considered "supertraits". These are required to be
acyclic. Supertraits are somewhat different from other constraints in that
they affect what methods are available in the vtable when the trait is used as
a [trait object].

Traits are implemented for specific types through separate [implementations].

### Associated functions and methods

Associated functions whose first parameter is named `self` are called methods
and may be invoked using `.` notation (e.g., `x.foo()`) as well as the usual
function call notation (`foo(x)`).

Consider the following trait:

```rust
Expand All @@ -903,9 +903,12 @@ trait Shape {

This defines a trait with two methods. All values that have [implementations]
of this trait in scope can have their `draw` and `bounding_box` methods called,
using `value.bounding_box()` [syntax].
using `value.bounding_box()` [syntax]. Note that `&self` is short for `self:
&Self`, and similarly, `self` is short for `self: Self` and `&mut self` is
short for `self: &mut Self`.

[trait object]: types.html#trait-objects [implementations]: #implementations
[trait object]: types.html#trait-objects
[implementations]: #implementations
[syntax]: expressions.html#method-call-expressions

Traits can include default implementations of methods, as in:
Expand Down Expand Up @@ -933,6 +936,26 @@ trait Seq<T> {
}
```

Associated functions may lack a `self` argument, sometimes called 'static
methods'. This means that they can only be called with function call syntax
(`f(x)`) and not method call syntax (`obj.f()`). The way to refer to the name
of a static method is to qualify it with the trait name or type name, treating
the trait name like a module. For example:

```rust
trait Num {
fn from_i32(n: i32) -> Self;
}
impl Num for f64 {
fn from_i32(n: i32) -> f64 { n as f64 }
}
let x: f64 = Num::from_i32(42);
let x: f64 = f64::from_i32(42);
```


### Associated Types

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:
Expand Down Expand Up @@ -962,32 +985,117 @@ impl<T> Container for Vec<T> {
}
```

### Associated Constants

A trait can define constants like this:

```rust
trait Foo {
const ID: i32;
}

impl Foo for i32 {
const ID: i32 = 1;
}

fn main() {
assert_eq!(1, i32::ID);
}
```

Any implementor of `Foo` will have to define `ID`. Without the definition:

```rust,compile_fail,E0046
trait Foo {
const ID: i32;
}
impl Foo for i32 {
}
```

gives

```text
error: not all trait items implemented, missing: `ID` [E0046]
impl Foo for i32 {
}
```

A default value can be implemented as well:

```rust
trait Foo {
const ID: i32 = 1;
}

impl Foo for i32 {
}

impl Foo for i64 {
const ID: i32 = 5;
}

fn main() {
assert_eq!(1, i32::ID);
assert_eq!(5, i64::ID);
}
```

As you can see, when implementing `Foo`, you can leave it unimplemented, as
with `i32`. It will then use the default value. But, as in `i64`, we can also
add our own definition.

Associated constants don’t have to be associated with a trait. An `impl` block
for a `struct` or an `enum` works fine too:

```rust
struct Foo;

impl Foo {
const FOO: u32 = 3;
}
```

### Trait bounds

Generic functions may use traits as _bounds_ on their type parameters. This
will have two effects:
will have three effects:

- Only types that have the trait may instantiate the parameter.
- Within the generic function, the methods of the trait can be called on values
that have the parameter's type.
that have the parameter's type. Associated types can be used in the
function's signature, and associated constants can be used in expressions
within the function body.
- Generic functions and types with the same or weaker bounds can use the
generic type in the function body or signature.

For example:

```rust
# type Surface = i32;
# trait Shape { fn draw(&self, Surface); }
struct Figure<S: Shape>(S, S);
fn draw_twice<T: Shape>(surface: Surface, sh: T) {
sh.draw(surface);
sh.draw(surface);
}
fn draw_figure<U: Shape>(surface: Surface, Figure(sh1, sh2): Figure<U>) {
sh1.draw(surface);
draw_twice(surface, sh2); // Can call this since U: Shape
}
```

### Trait objects

Traits also define a [trait object] with the same name as the trait. Values of
this type are created by coercing from a pointer of some specific type to a
pointer of trait type. For example, `&T` could be coerced to `&Shape` if `T:
Shape` holds (and similarly for `Box<T>`). This coercion can either be implicit
or [explicit]. Here is an example of an explicit coercion:

[trait object]: types.html#trait-objects [explicit]:
expressions.html#type-cast-expressions
[trait object]: types.html#trait-objects
[explicit]: expressions.html#type-cast-expressions

```rust
trait Shape { }
Expand All @@ -1004,24 +1112,13 @@ the trait.

[methods called]: expressions.html#method-call-expressions

Trait methods may be static, which means that they lack a `self` argument. This
means that they can only be called with function call syntax (`f(x)`) and not
method call syntax (`obj.f()`). The way to refer to the name of a static method
is to qualify it with the trait name or type name, treating the trait name like
a module. For example:
### Supertraits

```rust
trait Num {
fn from_i32(n: i32) -> Self;
}
impl Num for f64 {
fn from_i32(n: i32) -> f64 { n as f64 }
}
let x: f64 = Num::from_i32(42);
let x: f64 = f64::from_i32(42);
```

Traits may inherit from other traits. Consider the following example:
Trait bounds on `Self` are considered "supertraits". These are required to be
acyclic. Supertraits are somewhat different from other constraints in that
they affect what methods are available in the vtable when the trait is used as
a [trait object]. Consider the following example:

```rust
trait Shape { fn area(&self) -> f64; }
Expand Down Expand Up @@ -1082,79 +1179,6 @@ let mycircle = Box::new(mycircle) as Box<Circle>;
let nonsense = mycircle.radius() * mycircle.area();
```

### Associated Constants


A trait can define constants like this:

```rust
trait Foo {
const ID: i32;
}

impl Foo for i32 {
const ID: i32 = 1;
}

fn main() {
assert_eq!(1, i32::ID);
}
```

Any implementor of `Foo` will have to define `ID`. Without the definition:

```rust,compile_fail,E0046
trait Foo {
const ID: i32;
}
impl Foo for i32 {
}
```

gives

```text
error: not all trait items implemented, missing: `ID` [E0046]
impl Foo for i32 {
}
```

A default value can be implemented as well:

```rust
trait Foo {
const ID: i32 = 1;
}

impl Foo for i32 {
}

impl Foo for i64 {
const ID: i32 = 5;
}

fn main() {
assert_eq!(1, i32::ID);
assert_eq!(5, i64::ID);
}
```

As you can see, when implementing `Foo`, you can leave it unimplemented, as
with `i32`. It will then use the default value. But, as in `i64`, we can also
add our own definition.

Associated constants don’t have to be associated with a trait. An `impl` block
for a `struct` or an `enum` works fine too:

```rust
struct Foo;

impl Foo {
const FOO: u32 = 3;
}
```

## Implementations

An _implementation_ is an item that can implement a [trait](#traits) for a
Expand Down

0 comments on commit 7c8ff20

Please sign in to comment.