]> git.lizzy.rs Git - rust.git/blob - src/doc/unstable-book/src/conservative-impl-trait.md
Rollup merge of #40521 - TimNN:panic-free-shift, r=alexcrichton
[rust.git] / src / doc / unstable-book / src / conservative-impl-trait.md
1 # `conservative_impl_trait`
2
3 The tracking issue for this feature is: [#34511]
4
5 [#34511]: https://github.com/rust-lang/rust/issues/34511
6
7 ------------------------
8
9 The `conservative_impl_trait` feature allows a conservative form of abstract
10 return types.
11
12 Abstract return types allow a function to hide a concrete return type behind a
13 trait interface similar to trait objects, while still generating the same
14 statically dispatched code as with concrete types.
15
16 ## Examples
17
18 ```rust
19 #![feature(conservative_impl_trait)]
20
21 fn even_iter() -> impl Iterator<Item=u32> {
22     (0..).map(|n| n * 2)
23 }
24
25 fn main() {
26     let first_four_even_numbers = even_iter().take(4).collect::<Vec<_>>();
27     assert_eq!(first_four_even_numbers, vec![0, 2, 4, 6]);
28 }
29 ```
30
31 ## Background
32
33 In today's Rust, you can write function signatures like:
34
35 ````rust,ignore
36 fn consume_iter_static<I: Iterator<u8>>(iter: I) { }
37
38 fn consume_iter_dynamic(iter: Box<Iterator<u8>>) { }
39 ````
40
41 In both cases, the function does not depend on the exact type of the argument.
42 The type held is "abstract", and is assumed only to satisfy a trait bound.
43
44 * In the `_static` version using generics, each use of the function is
45   specialized to a concrete, statically-known type, giving static dispatch,
46   inline layout, and other performance wins.
47 * In the `_dynamic` version using trait objects, the concrete argument type is
48   only known at runtime using a vtable.
49
50 On the other hand, while you can write:
51
52 ````rust,ignore
53 fn produce_iter_dynamic() -> Box<Iterator<u8>> { }
54 ````
55
56 ...but you _cannot_ write something like:
57
58 ````rust,ignore
59 fn produce_iter_static() -> Iterator<u8> { }
60 ````
61
62 That is, in today's Rust, abstract return types can only be written using trait
63 objects, which can be a significant performance penalty. This RFC proposes
64 "unboxed abstract types" as a way of achieving signatures like
65 `produce_iter_static`. Like generics, unboxed abstract types guarantee static
66 dispatch and inline data layout.