]> git.proxmox.com Git - rustc.git/blame - src/doc/book/generics.md
New upstream version 1.16.0+dfsg1
[rustc.git] / src / doc / book / generics.md
CommitLineData
1a4d82fc
JJ
1% Generics
2
3Sometimes, when writing a function or data type, we may want it to work for
62682a34
SL
4multiple types of arguments. In Rust, we can do this with generics.
5Generics are called ‘parametric polymorphism’ in type theory,
bd371182
AL
6which means that they are types or functions that have multiple forms (‘poly’
7is multiple, ‘morph’ is form) over a given parameter (‘parametric’).
1a4d82fc 8
e9174d1e 9Anyway, enough type theory, let’s check out some generic code. Rust’s
bd371182 10standard library provides a type, `Option<T>`, that’s generic:
1a4d82fc
JJ
11
12```rust
13enum Option<T> {
14 Some(T),
15 None,
16}
17```
18
bd371182 19The `<T>` part, which you’ve seen a few times before, indicates that this is
e9174d1e 20a generic data type. Inside the declaration of our `enum`, wherever we see a `T`,
bd371182 21we substitute that type for the same type used in the generic. Here’s an
1a4d82fc
JJ
22example of using `Option<T>`, with some extra type annotations:
23
bd371182 24```rust
85aaf69f 25let x: Option<i32> = Some(5);
1a4d82fc
JJ
26```
27
85aaf69f
SL
28In the type declaration, we say `Option<i32>`. Note how similar this looks to
29`Option<T>`. So, in this particular `Option`, `T` has the value of `i32`. On
e9174d1e 30the right-hand side of the binding, we make a `Some(T)`, where `T` is `5`.
bd371182
AL
31Since that’s an `i32`, the two sides match, and Rust is happy. If they didn’t
32match, we’d get an error:
1a4d82fc 33
bd371182 34```rust,ignore
85aaf69f
SL
35let x: Option<f64> = Some(5);
36// error: mismatched types: expected `core::option::Option<f64>`,
37// found `core::option::Option<_>` (expected f64 but found integral variable)
1a4d82fc
JJ
38```
39
9cc50fc6 40That doesn’t mean we can’t make `Option<T>`s that hold an `f64`! They have
bd371182 41to match up:
1a4d82fc 42
bd371182 43```rust
85aaf69f 44let x: Option<i32> = Some(5);
1a4d82fc
JJ
45let y: Option<f64> = Some(5.0f64);
46```
47
48This is just fine. One definition, multiple uses.
49
bd371182 50Generics don’t have to only be generic over one type. Consider another type from Rust’s standard library that’s similar, `Result<T, E>`:
1a4d82fc 51
bd371182 52```rust
1a4d82fc
JJ
53enum Result<T, E> {
54 Ok(T),
55 Err(E),
56}
57```
58
59This type is generic over _two_ types: `T` and `E`. By the way, the capital letters
bd371182 60can be any letter you’d like. We could define `Result<T, E>` as:
1a4d82fc 61
bd371182 62```rust
85aaf69f
SL
63enum Result<A, Z> {
64 Ok(A),
65 Err(Z),
1a4d82fc
JJ
66}
67```
68
69if we wanted to. Convention says that the first generic parameter should be
bd371182 70`T`, for ‘type’, and that we use `E` for ‘error’. Rust doesn’t care, however.
1a4d82fc 71
85aaf69f 72The `Result<T, E>` type is intended to be used to return the result of a
bd371182 73computation, and to have the ability to return an error if it didn’t work out.
1a4d82fc 74
bd371182 75## Generic functions
1a4d82fc 76
bd371182 77We can write functions that take generic types with a similar syntax:
1a4d82fc 78
bd371182
AL
79```rust
80fn takes_anything<T>(x: T) {
476ff2be 81 // Do something with `x`.
1a4d82fc
JJ
82}
83```
84
bd371182
AL
85The syntax has two parts: the `<T>` says “this function is generic over one
86type, `T`”, and the `x: T` says “x has the type `T`.”
1a4d82fc 87
bd371182 88Multiple arguments can have the same generic type:
1a4d82fc 89
bd371182
AL
90```rust
91fn takes_two_of_the_same_things<T>(x: T, y: T) {
92 // ...
1a4d82fc
JJ
93}
94```
95
bd371182 96We could write a version that takes multiple types:
1a4d82fc 97
bd371182
AL
98```rust
99fn takes_two_things<T, U>(x: T, y: U) {
100 // ...
1a4d82fc
JJ
101}
102```
103
bd371182 104## Generic structs
1a4d82fc 105
bd371182 106You can store a generic type in a `struct` as well:
1a4d82fc 107
62682a34 108```rust
bd371182
AL
109struct Point<T> {
110 x: T,
111 y: T,
112}
1a4d82fc 113
bd371182
AL
114let int_origin = Point { x: 0, y: 0 };
115let float_origin = Point { x: 0.0, y: 0.0 };
116```
1a4d82fc 117
e9174d1e 118Similar to functions, the `<T>` is where we declare the generic parameters,
bd371182 119and we then use `x: T` in the type declaration, too.
e9174d1e 120
9cc50fc6 121When you want to add an implementation for the generic `struct`, you
e9174d1e
SL
122declare the type parameter after the `impl`:
123
124```rust
125# struct Point<T> {
126# x: T,
127# y: T,
128# }
129#
130impl<T> Point<T> {
131 fn swap(&mut self) {
132 std::mem::swap(&mut self.x, &mut self.y);
133 }
134}
135```
136
137So far you’ve seen generics that take absolutely any type. These are useful in
138many cases: you’ve already seen `Option<T>`, and later you’ll meet universal
139container types like [`Vec<T>`][Vec]. On the other hand, often you want to
140trade that flexibility for increased expressive power. Read about [trait
141bounds][traits] to see why and how.
142
143[traits]: traits.html
144[Vec]: ../std/vec/struct.Vec.html