]> git.proxmox.com Git - rustc.git/blob - src/doc/reference/src/items/traits.md
cca70b09b502226b58559945198bcd78f849cb70
[rustc.git] / src / doc / reference / src / items / traits.md
1 # Traits
2
3 A _trait_ describes an abstract interface that types can implement. This
4 interface consists of [associated items], which come in three varieties:
5
6 - [functions](items/associated-items.html#associated-functions-and-methods)
7 - [types](items/associated-items.html#associated-types)
8 - [constants](items/associated-items.html#associated-constants)
9
10 All traits define an implicit type parameter `Self` that refers to "the type
11 that is implementing this interface". Traits may also contain additional type
12 parameters. These type parameters (including `Self`) may be constrained by
13 other traits and so forth as usual.
14
15 Traits are implemented for specific types through separate [implementations].
16
17 ## Trait bounds
18
19 Generic functions may use traits as _bounds_ on their type parameters. This
20 will have three effects:
21
22 - Only types that have the trait may instantiate the parameter.
23 - Within the generic function, the methods of the trait can be called on values
24 that have the parameter's type. Associated types can be used in the
25 function's signature, and associated constants can be used in expressions
26 within the function body.
27 - Generic functions and types with the same or weaker bounds can use the
28 generic type in the function body or signature.
29
30 For example:
31
32 ```rust
33 # type Surface = i32;
34 # trait Shape { fn draw(&self, Surface); }
35 struct Figure<S: Shape>(S, S);
36 fn draw_twice<T: Shape>(surface: Surface, sh: T) {
37 sh.draw(surface);
38 sh.draw(surface);
39 }
40 fn draw_figure<U: Shape>(surface: Surface, Figure(sh1, sh2): Figure<U>) {
41 sh1.draw(surface);
42 draw_twice(surface, sh2); // Can call this since U: Shape
43 }
44 ```
45
46 ## Generic Traits
47
48 Type parameters can be specified for a trait to make it generic. These appear
49 after the trait name, using the same syntax used in [generic
50 functions](items/functions.html#generic-functions).
51
52 ```rust
53 trait Seq<T> {
54 fn len(&self) -> u32;
55 fn elt_at(&self, n: u32) -> T;
56 fn iter<F>(&self, F) where F: Fn(T);
57 }
58 ```
59
60 ## Object Safety
61
62 Object safe traits can be the base trait of a [trait object]. A trait is
63 *object safe* if it has the following qualities (defined in [RFC 255]):
64
65 * It must not require `Self: Sized`
66 * All associated functions must either have a `where Self: Sized` bound or
67 * Not have any type parameters (although lifetime parameters are allowed)
68 * Must be a method: its first parameter must be called self, with type
69 `Self`, `&Self`, `&mut Self`, `Box<Self>`.
70 * `Self` may only be used in the type of the receiver.
71 * It must not have any associated constants.
72
73 ## Supertraits
74
75 Trait bounds on `Self` are considered "supertraits". These are required to be
76 acyclic. Supertraits are somewhat different from other constraints in that
77 they affect what methods are available in the vtable when the trait is used as
78 a [trait object]. Consider the following example:
79
80 ```rust
81 trait Shape { fn area(&self) -> f64; }
82 trait Circle : Shape { fn radius(&self) -> f64; }
83 ```
84
85 The syntax `Circle : Shape` means that types that implement `Circle` must also
86 have an implementation for `Shape`. Multiple supertraits are separated by `+`,
87 `trait Circle : Shape + PartialEq { }`. In an implementation of `Circle` for a
88 given type `T`, methods can refer to `Shape` methods, since the typechecker
89 checks that any type with an implementation of `Circle` also has an
90 implementation of `Shape`:
91
92 ```rust
93 struct Foo;
94
95 trait Shape { fn area(&self) -> f64; }
96 trait Circle : Shape { fn radius(&self) -> f64; }
97 impl Shape for Foo {
98 fn area(&self) -> f64 {
99 0.0
100 }
101 }
102 impl Circle for Foo {
103 fn radius(&self) -> f64 {
104 println!("calling area: {}", self.area());
105
106 0.0
107 }
108 }
109
110 let c = Foo;
111 c.radius();
112 ```
113
114 In type-parameterized functions, methods of the supertrait may be called on
115 values of subtrait-bound type parameters. Referring to the previous example of
116 `trait Circle : Shape`:
117
118 ```rust
119 # trait Shape { fn area(&self) -> f64; }
120 # trait Circle : Shape { fn radius(&self) -> f64; }
121 fn radius_times_area<T: Circle>(c: T) -> f64 {
122 // `c` is both a Circle and a Shape
123 c.radius() * c.area()
124 }
125 ```
126
127 Likewise, supertrait methods may also be called on trait objects.
128
129 ```rust
130 # trait Shape { fn area(&self) -> f64; }
131 # trait Circle : Shape { fn radius(&self) -> f64; }
132 # impl Shape for i32 { fn area(&self) -> f64 { 0.0 } }
133 # impl Circle for i32 { fn radius(&self) -> f64 { 0.0 } }
134 # let mycircle = 0i32;
135 let mycircle = Box::new(mycircle) as Box<Circle>;
136 let nonsense = mycircle.radius() * mycircle.area();
137 ```
138
139 [`Send`]: ../std/marker/trait.Send.html
140 [`Send`]: ../std/marker/trait.Sync.html
141 [`UnwindSafe`]: ../std/panic/trait.UnwindSafe.html
142 [`RefUnwindSafe`]: ../std/panic/trait.RefUnwindSafe.html
143 [trait object]: types.html#trait-objects
144 [explicit]: expressions/operator-expr.html#type-cast-expressions
145 [methods called]: expressions/method-call-expr.html
146 [RFC 255]: https://github.com/rust-lang/rfcs/blob/master/text/0255-object-safety.md
147 [associated items]: items/associated-items.html