Skip to content

Commit

Permalink
Merge pull request #146 from Havvy/impl
Browse files Browse the repository at this point in the history
Implementations improvements part 1
  • Loading branch information
steveklabnik authored Dec 8, 2017
2 parents cf2fbba + a051754 commit 13f02d1
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 26 deletions.
27 changes: 23 additions & 4 deletions src/glossary.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,22 @@ the structure of the program when the compiler is compiling it.

### Arity

Arity refers to the number of arguments a function or operation takes.
For example, `(2, 3)` and `(4, 6)` have arity 2, and`(8, 2, 6)` has arity 3.
Arity refers to the number of arguments a function or operator takes.
For some examples, `f(2, 3)` and `g(4, 6)` have arity 2, while `h(8, 2, 6)`
has arity 3. The `!` operator has arity 1.

### Array

An array, sometimes also called a fixed-size array or an inline array, is a value
describing a collection of elements, each selected by an index that can be computed
at run time by the program. It occupies a contiguous region of memory.

### Associated Item

An associated item is an item that is associated with another item. Associated
items are defined in [implementations] and declared in [traits]. Only functions,
constants, and type aliases can be associated.

### Bound

Bounds are constraints on a type or trait. For example, if a bound
Expand Down Expand Up @@ -52,6 +59,11 @@ A variable is initialized if it has been assigned a value and hasn't since been
moved from. All other lvalues are assumed to be initialized. Only unsafe Rust
can create such an lvalue without initializing it.

### Nominal Types

Types that can be referred to by a path directly. Specifically [enums],
[structs], [unions], and [trait objects].

### Prelude

Prelude, or The Rust Prelude, is a small collection of items - mostly traits - that are
Expand Down Expand Up @@ -88,6 +100,13 @@ Strings slices are always valid UTF-8.
### Trait

A trait is a language item that is used for describing the functionalities a type must provide.
It allow a type to make certain promises about its behavior.
It allows a type to make certain promises about its behavior.

Generic functions and generic structs can use traits to constrain, or bound, the types they accept.

Generic functions and generic structs can exploit traits to constrain, or bound, the types they accept.
[enums]: items/enumerations.html
[structs]: items/structs.html
[unions]: items/unions.html
[trait objects]: types.html#trait-objects
[implementations]: items/implementations.html
[traits]: items/traits.html
108 changes: 86 additions & 22 deletions src/items/implementations.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,65 @@
# Implementations

An _implementation_ is an item that can implement a [trait](items/traits.html) for a
specific type.
An _implementation_ is an item that associates items with an *implementing type*.

There are two types of implementations: inherent implementations and [trait]
implementations.

Implementations are defined with the keyword `impl`.

## Interent Implementations

An inherent implementation is defined as the sequence of the `impl` keyword,
generic type declarations, a path to a nomial type, a where clause, and a
bracketed set of associable items.

The nominal type is called the *implementing type* and the associable items are
the *associated items* to the implementing type.

Inherent implementations associate the associated items to the implementing
type.

The associated item has a path of a path to the implementing type followed by
the associate item's path component.

Inherent implementations cannot contain associated type aliases.

A type can have multiple inherent implementations.

The implementing type must be defined within the same crate.

```rust
struct Point {x: i32, y: i32}

impl Point {
fn log(&self) {
println!("Point is at ({}, {})", self.x, self.y);
}
}

let my_point = Point {x: 10, y:11};
my_point.log();
```

## Trait Implementations

A *trait implementation* is defined like an inherent implementation except that
the optional generic type declarations is followed by a [trait] followed
by the keyword `for`. <!-- To understand this, you have to back-reference to
the previous section. :( -->

The trait is known as the *implemented trait*.

The implementing type implements the implemented trait.

A trait implementation must define all non-default associated items declared
by the implemented trait, may redefine default associated items defined by the
implemented trait trait, and cannot define any other items.

The path to the associated items is `<` followed by a path to the implementing
type followed by `as` followed by a path to the trait followed by `>` as a path
component followed by the associated item's path component.

```rust
# #[derive(Copy, Clone)]
# struct Point {x: f64, y: f64};
Expand Down Expand Up @@ -37,33 +92,39 @@ impl Shape for Circle {
}
```

It is possible to define an implementation without referring to a trait. The
methods in such an implementation can only be used as direct calls on the
values of the type that the implementation targets. In such an implementation,
the trait type and `for` after `impl` are omitted. Such implementations are
limited to nominal types (enums, structs, unions, trait objects), and the
implementation must appear in the same crate as the `Self` type:
### Trait Implementation Coherence

```rust
struct Point {x: i32, y: i32}
A trait implementation is consider incoherent if either the orphan check fails
or there are overlapping implementation instaces.

impl Point {
fn log(&self) {
println!("Point is at ({}, {})", self.x, self.y);
}
}
Two trait implementations overlap when there is a non-empty intersection of the
traits the implementation is for, the implementations can be instantiated with
the same type. <!-- This is probably wrong? Source: No two implementations can
be instantiable with the same set of types for the input type parameters. -->

let my_point = Point {x: 10, y:11};
my_point.log();
```
The `Orphan Check` states that every trait implementation must meet either of
the following conditions:

When a trait _is_ specified in an `impl`, all methods declared as part of the
trait must be implemented, with matching types and type parameter counts.
1. The trait being implemented is defined in the same crate.

2. At least one of either `Self` or a generic type parameter of the trait must
meet the following grammar, where `C` is a nominal type defined
within the containing crate:

```ignore
T = C
| &T
| &mut T
| Box<T>
```

## Generic Implementations

An implementation can take type and lifetime parameters, which can be used in
the rest of the implementation. Type parameters declared for an implementation
must be used at least once in either the trait or the type of an
implementation. Implementation parameters are written after the `impl` keyword.
must be used at least once in either the trait or the implementing type of an
implementation. Implementation parameters are written directly after the `impl`
keyword.

```rust
# trait Seq<T> { fn dummy(&self, _: T) { } }
Expand All @@ -74,3 +135,6 @@ impl Seq<bool> for u32 {
/* Treat the integer as a sequence of bits */
}
```


[trait]: items/traits.html

0 comments on commit 13f02d1

Please sign in to comment.