Skip to content

Commit 20008b5

Browse files
committed
Fix rust-lang#1060: document impl Trait on its own page and others
1 parent 37a2861 commit 20008b5

File tree

3 files changed

+55
-9
lines changed

3 files changed

+55
-9
lines changed

src/SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@
137137
- [Operator Overloading](trait/ops.md)
138138
- [Drop](trait/drop.md)
139139
- [Iterators](trait/iter.md)
140+
- [impl Trait](trait/impl_trait.md)
140141
- [Clone](trait/clone.md)
141142

142143
- [macro_rules!](macros.md)

src/fn/closures/output_parameters.md

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@
33
Closures as input parameters are possible, so returning closures as
44
output parameters should also be possible. However, returning closure types
55
are problematic because Rust currently only supports returning concrete
6-
(non-generic) types. Anonymous closure types are, by definition, unknown
7-
and so returning a closure is only possible by making it concrete. This
8-
can be done via boxing.
6+
(non-generic) types. Anonymous closure types are, by definition, unknown,
7+
so we can use `impl Trait` to return them.
98

109
The valid traits for returns are slightly different than before:
1110

@@ -21,16 +20,16 @@ dropped as soon as the function exited, leaving invalid references in the
2120
closure.
2221

2322
```rust,editable
24-
fn create_fn() -> Box<Fn()> {
23+
fn create_fn() -> impl Fn() {
2524
let text = "Fn".to_owned();
2625
27-
Box::new(move || println!("This is a: {}", text))
26+
move || println!("This is a: {}", text)
2827
}
2928
30-
fn create_fnmut() -> Box<FnMut()> {
29+
fn create_fnmut() -> impl FnMut() {
3130
let text = "FnMut".to_owned();
3231
33-
Box::new(move || println!("This is a: {}", text))
32+
move || println!("This is a: {}", text)
3433
}
3534
3635
fn main() {
@@ -44,10 +43,10 @@ fn main() {
4443

4544
### See also:
4645

47-
[Boxing][box], [`Fn`][fn], [`FnMut`][fnmut], and [Generics][generics].
46+
[`Fn`][fn], [`FnMut`][fnmut], [Generics][generics] and [impl Trait][impltrait].
4847

49-
[box]: ../../std/box.md
5048
[fn]: https://doc.rust-lang.org/std/ops/trait.Fn.html
5149
[fnmut]: https://doc.rust-lang.org/std/ops/trait.FnMut.html
5250
[fnbox]: https://doc.rust-lang.org/std/boxed/trait.FnBox.html
5351
[generics]: ../../generics.md
52+
[impltrait]: ../../traits/impl_trait.md

src/trait/impl_trait.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# impl Trait
2+
3+
If your function returns a type that implements `MyTrait`, you can write its return type as `-> impl MyTrait`. This can help simplify your type signatures quite a lot!
4+
5+
```rust,editable
6+
use std::iter;
7+
use std::vec::IntoIter;
8+
9+
// This function combines two Vec<i32> and returns an iterator over it.
10+
// Look how complicated its return type is!
11+
fn combine_vecs_explicit_return_type<'a>(
12+
v: Vec<i32>,
13+
u: Vec<i32>,
14+
) -> iter::Cycle<iter::Chain<IntoIter<i32>, IntoIter<i32>>> {
15+
v.into_iter().chain(u.into_iter()).cycle()
16+
}
17+
18+
// This is the exact same function, but its return type uses `impl Trait`.
19+
// Look how much simpler it is!
20+
fn combine_vecs<'a>(
21+
v: Vec<i32>,
22+
u: Vec<i32>,
23+
) -> impl Iterator<Item=i32> {
24+
v.into_iter().chain(u.into_iter()).cycle()
25+
}
26+
```
27+
28+
More importantly, some Rust types can't be written out. For example, every closure has its own unnamed concrete type. Before `impl Trait` syntax, you couldn't write a function like this:
29+
30+
```rust,editable
31+
fn return_closure() -> impl Fn(i32) {
32+
let closure = |x: i32| { println!("the value of x is {}", x) };
33+
closure
34+
}
35+
```
36+
37+
Here's a more realistic example: what if you want to return an iterator that uses `map` or `filter` closures? Because the closure's types don't have names, you can't write out an explicit return type. But with `impl Trait` you can do this easily:
38+
39+
```rust,editable
40+
fn double_positives<'a>(numbers: &'a Vec<i32>) -> impl Iterator<Item = i32> + 'a {
41+
numbers
42+
.iter()
43+
.filter(|x| x > &&0)
44+
.map(|x| x * 2)
45+
}
46+
```

0 commit comments

Comments
 (0)