You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Use only the closure example to illustrate the difference between
returning trait objects vs `impl Trait`. Also mention usefulness in
returning iterators.
Copy file name to clipboardExpand all lines: src/types/impl-trait.md
+12-43Lines changed: 12 additions & 43 deletions
Original file line number
Diff line number
Diff line change
@@ -61,63 +61,32 @@ Functions can use `impl Trait` to return an abstract return type.
61
61
These types stand in for another concrete type where the caller may only use the methods declared by the specified `Trait`.
62
62
Each possible return value from the function must resolve to the same concrete type.
63
63
64
-
Prior to `impl Trait`, a function could express abstract return types by using [trait objects]:
65
-
66
-
```rust
67
-
traitTrait {}
68
-
69
-
implTraitfori32 {}
70
-
71
-
fnreturns_a_trait_object() ->Box<dynTrait> {
72
-
Box::new(5)
73
-
}
74
-
```
75
-
76
-
This has some drawbacks: constructing `Box<T>` involves a heap allocation, and the `dyn Trait` will use dynamic dispatch on its methods.
77
-
However, this function only returns one possible type here: the `Box<i32>`.
78
-
This means incurring the costs of dynamic dispatch, even though the return type cannot vary.
79
-
80
-
With `impl Trait`, the code above could be written like this:
81
-
82
-
```rust
83
-
traitTrait {}
84
-
85
-
implTraitfori32 {}
86
-
87
-
fnreturns_a_trait_object() ->implTrait {
88
-
5
89
-
}
90
-
```
91
-
92
-
There is no `Box<T>`, no trait object, and no dynamic dispatch.
93
-
However, the function can still can obscure the `i32` return type.
94
-
95
-
With `i32`, this might not seem very useful.
96
-
There is one major place in Rust where this is much more useful: closures.
97
-
98
-
### `impl Trait` and closures
99
-
100
-
In Rust, [closures] have a unique, un-writable type.
101
-
However, they do implement the `Fn` family of traits.
102
-
This means that previously, the only way to return a closure from a function was to use a trait object:
64
+
`impl Trait` in return position allows a function to return an unboxed abstract type.
65
+
This is particularly useful with [closures] and iterators.
66
+
For example, closures have a unique, un-writable type.
67
+
Previously, the only way to return a closure from a function was to use a [trait object]:
103
68
104
69
```rust
105
70
fnreturns_closure() ->Box<dynFn(i32) ->i32> {
106
71
Box::new(|x|x+1)
107
72
}
108
73
```
109
74
110
-
It wasn't possible to fully specify the type of the closure, only use the `Fn` trait.
75
+
This could incur performance penalties from heap allocation and dynamic dispatch.
76
+
It wasn't possible to fully specify the type of the closure, only to use the `Fn` trait.
111
77
That means that the trait object is necessary.
112
-
However, with `impl Trait`:
78
+
However, with `impl Trait`, it is possible to write this more simply:
113
79
114
80
```rust
115
81
fnreturns_closure() ->implFn(i32) ->i32 {
116
82
|x|x+1
117
83
}
118
84
```
119
85
120
-
It is now possible to return closures by value, just like any other type.
86
+
which also avoids the drawbacks of using a boxed trait object.
87
+
88
+
Similarly, the concrete types of iterators could become very complex, incorporating the types of all previous iterators in a chain.
89
+
Returning `impl Iterator` means that a function only exposes the `Iterator` trait as a bound on its return type, instead of explicitly specifying all of the other iterator types involved.
121
90
122
91
### Differences between generics and `impl Trait` in return position
123
92
@@ -151,5 +120,5 @@ It cannot appear inside implementations of traits, nor can it be the type of a l
0 commit comments