|
1 |
| -# Trait bounds |
| 1 | +# Trait and lifetime bounds |
2 | 2 |
|
3 |
| -Generic functions may use traits as _bounds_ on their type parameters. This |
4 |
| -will have three effects: |
| 3 | +> **<sup>Syntax</sup>** |
| 4 | +> _TypeParamBounds_ : |
| 5 | +> _TypeParamBound_ ( `+` _TypeParamBound_ )<sup>\*</sup> `+`<sup>?</sup> |
| 6 | +> |
| 7 | +> _TypeParamBound_ : |
| 8 | +> [_Lifetime_] | _TraitBound_ |
| 9 | +> |
| 10 | +> _TraitBound_ : |
| 11 | +> `?`<sup>?</sup>[^sized_only] |
| 12 | +> [_ForLifetimes_](#higher-ranked-trait-bounds)<sup>?</sup> [_TraitPath_] |
| 13 | +> | `(` `?`<sup>?</sup> |
| 14 | +> [_ForLifetimes_](#higher-ranked-trait-bounds)<sup>?</sup> [_TraitPath_] `)` |
| 15 | +> |
| 16 | +> _LifetimeBounds_ : |
| 17 | +> `:` [_Lifetime_] ( `+` [_Lifetime_] )<sup>\*</sup> `+`<sup>?</sup> |
5 | 18 |
|
6 |
| -- Only types that have the trait may instantiate the parameter. |
7 |
| -- Within the generic function, the methods of the trait can be called on values |
8 |
| - that have the parameter's type. Associated types can be used in the |
9 |
| - function's signature, and associated constants can be used in expressions |
10 |
| - within the function body. |
11 |
| -- Generic functions and types with the same or weaker bounds can use the |
12 |
| - generic type in the function body or signature. |
| 19 | +[Trait] and lifetime bounds provide a way for [generic items][generic] to |
| 20 | +restrict which types and lifetimes are used as their parameters. Bounds can be |
| 21 | +provided on any type in a [where clause]. There are also shorter alternative |
| 22 | +forms: |
13 | 23 |
|
14 |
| -For example: |
| 24 | +* Bounds written after declaring a [generic parameter][generic]: |
| 25 | + `fn f<A: Copy>() {}` is the same as `fn f<A> where A: Copy () {}`. |
| 26 | +* In trait declarations as [supertraits]: `trait Circle : Shape {}` is |
| 27 | + equivalent to `trait Circle where Self : Shape {}`. |
| 28 | +* In trait declarations as bounds on [associated types]: |
| 29 | + `trait A { type B: Copy; }` is equivalent to |
| 30 | + `trait A where Self::B: Copy { type B; }`. |
| 31 | + |
| 32 | +Bounds on an item must be satisfied when using the item. When type checking |
| 33 | +and borrow checking the item, the bounds can be used to prove that a type |
| 34 | +implements a required bound. |
15 | 35 |
|
16 | 36 | ```rust
|
17 | 37 | # type Surface = i32;
|
18 |
| -# trait Shape { fn draw(&self, Surface); } |
19 |
| -struct Figure<S: Shape>(S, S); |
| 38 | +trait Shape { |
| 39 | + fn draw(&self, Surface); |
| 40 | + fn name() -> &'static str; |
| 41 | +} |
| 42 | + |
20 | 43 | fn draw_twice<T: Shape>(surface: Surface, sh: T) {
|
| 44 | + sh.draw(surface); // Can call method because T: Shape |
21 | 45 | sh.draw(surface);
|
22 |
| - sh.draw(surface); |
23 | 46 | }
|
24 |
| -fn draw_figure<U: Shape>(surface: Surface, Figure(sh1, sh2): Figure<U>) { |
25 |
| - sh1.draw(surface); |
26 |
| - draw_twice(surface, sh2); // Can call this since U: Shape |
| 47 | + |
| 48 | +fn copy_and_draw_twice<T: Copy>(surface: Surface, sh: T) where T: Shape { |
| 49 | + let shape_copy = sh; // doesn't move sh because T: Copy |
| 50 | + draw_twice(surface, sh); // Can use generic function because T: Shape |
| 51 | +} |
| 52 | + |
| 53 | +struct Figure<S: Shape>(S, S); |
| 54 | + |
| 55 | +fn name_figure<U: Shape>( |
| 56 | + figure: Figure<U>, // Type Figure<U> is well-formed because U: Shape |
| 57 | +) { |
| 58 | + println!( |
| 59 | + "Figure of two {}", |
| 60 | + U::name(), // Can use associated function |
| 61 | + ); |
| 62 | +} |
| 63 | +``` |
| 64 | + |
| 65 | +Trait and lifetime bounds are also used to name [trait objects]. |
| 66 | + |
| 67 | +> [^sized_only] `?` is only used to declare that the [`Sized`] trait may not be |
| 68 | +> implemented for a type parameter or associated type. |
| 69 | +
|
| 70 | +## Lifetime bounds |
| 71 | + |
| 72 | +Lifetime bounds can be applied to other lifetimes, or to types. The bound |
| 73 | +`'a: 'b` is usually read as `'a` *outlives* `'b`. `'a: 'b` means that `'a` |
| 74 | +includes all points in the code that `'b` does. |
| 75 | + |
| 76 | +```rust |
| 77 | +fn f<'a, 'b>(x: &'a i32, mut y: &'b i32) where 'a: 'b { |
| 78 | + y = x; // &'a i32 is a subtype of &'b i32 because 'a: 'b |
| 79 | + let r: &'b &'a i32 = &&0; // &'b &'a i32 is well formed because 'a: 'b |
| 80 | +} |
| 81 | +``` |
| 82 | + |
| 83 | +`T: 'a` means that all lifetime parameters of `T` outlive `'a`. For example if |
| 84 | +`'a` is an unconstrained lifetime parameter then `i32: 'static` and |
| 85 | +`&'static str: 'a` are satisfied but `Vec<&'a ()>: 'static` is not. |
| 86 | + |
| 87 | +## Higher-ranked trait bounds |
| 88 | + |
| 89 | +> **<sup>Syntax</sup>** |
| 90 | +> _ForLifetimes_ : |
| 91 | +> `for` `<` ( [_LifetimeParams_][generic][^unused_for_bounds] |
| 92 | +> `,`<sup>?</sup> ) <sup>?</sup> `>` |
| 93 | +
|
| 94 | +Type bounds may be *higher ranked* over lifetimes. A bound such as `for<'a> &'a |
| 95 | +T: PartialEq<T>` can be used to show `&'a T: PartialEq<T>` for any lifetime. |
| 96 | +For example, only a higher-ranked bound can be used here as the lifetime of the |
| 97 | +reference is shorter than any lifetime parameter on the function: |
| 98 | + |
| 99 | +```rust |
| 100 | +fn call_on_ref_zero<F>(f: F) where for<'a> F: Fn(&'a i32) { |
| 101 | + let zero = 0; |
| 102 | + f(&zero); |
27 | 103 | }
|
28 | 104 | ```
|
| 105 | + |
| 106 | +Higher-ranked lifetimes may also be specified just before the trait, the only |
| 107 | +difference is the scope of the lifetime parameter, which extends only to the |
| 108 | +end of the following trait instead of the whole bound. This function is |
| 109 | +equivalent to the last one. |
| 110 | + |
| 111 | +```rust |
| 112 | +fn call_on_ref_zero<F>(f: F) where F: for<'a> Fn(&'a i32) { |
| 113 | + let zero = 0; |
| 114 | + f(&zero); |
| 115 | +} |
| 116 | +``` |
| 117 | + |
| 118 | +> [^unused_for_bounds]Warning: lifetime bounds are allowed on lifetimes in a |
| 119 | +> `for` binder, but have no effect: `for<'a, 'b: 'a>` is no different to |
| 120 | +> `for<'a, 'b>`. |
| 121 | +
|
| 122 | +[_Lifetime_]: items/generics.html |
| 123 | +[_TraitPath_]: paths.html |
| 124 | +[`Sized`]: special-types-and-traits.html#sized |
| 125 | + |
| 126 | +[associated types]: items/associated-items.html#associated-types |
| 127 | +[supertraits]: items/traits.html#supertraits |
| 128 | +[generic]: items/generics.html |
| 129 | +[Trait]: traits.html#trait-bounds |
| 130 | +[trait objects]: types.html#trait-objects |
| 131 | +[where clause]: items/where-clauses.html |
0 commit comments