Skip to content

Commit 09fbf05

Browse files
committed
Add capturing and precise capturing rules
The Reference didn't include any description of capturing or capturing behavior for `impl Trait` opaque types. Let's describe briefly what capturing is and what the currently-stable automatic capturing rules are. Then let's describe the syntax and behavior of RFC 3617 precise capturing. Precise capturing is currently undergoing stabilization in: - rust-lang/rust#127672 Tracking issue: - rust-lang/rust#123432
1 parent 8c789ff commit 09fbf05

File tree

2 files changed

+51
-4
lines changed

2 files changed

+51
-4
lines changed

src/trait-bounds.md

+21-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
> &nbsp;&nbsp; _TypeParamBound_ ( `+` _TypeParamBound_ )<sup>\*</sup> `+`<sup>?</sup>
66
>
77
> _TypeParamBound_ :\
8-
> &nbsp;&nbsp; &nbsp;&nbsp; _Lifetime_ | _TraitBound_
8+
> &nbsp;&nbsp; &nbsp;&nbsp; _Lifetime_ | _TraitBound_ | _UseBound_
99
>
1010
> _TraitBound_ :\
1111
> &nbsp;&nbsp; &nbsp;&nbsp; `?`<sup>?</sup>
@@ -19,6 +19,20 @@
1919
> _Lifetime_ :\
2020
> &nbsp;&nbsp; &nbsp;&nbsp; [LIFETIME_OR_LABEL]\
2121
> &nbsp;&nbsp; | `'static`
22+
>
23+
> _UseBound_ :\
24+
> &nbsp;&nbsp; `use` _UseBoundGenericArgs_
25+
>
26+
> _UseBoundGenericArgs_ :\
27+
> &nbsp;&nbsp; &nbsp;&nbsp; `<` `>` \
28+
> &nbsp;&nbsp; | `<` \
29+
> &nbsp;&nbsp; &nbsp;&nbsp; ( _UseBoundGenericArg_ `,`)<sup>\*</sup> \
30+
> &nbsp;&nbsp; &nbsp;&nbsp; _UseBoundGenericArg_ `,`<sup>?</sup> \
31+
> &nbsp;&nbsp; &nbsp;&nbsp; `>`
32+
>
33+
> _UseBoundGenericArg_ :\
34+
> &nbsp;&nbsp; &nbsp;&nbsp; [LIFETIME_OR_LABEL][] \
35+
> &nbsp;&nbsp; | [IDENTIFIER][]
2236
2337
[Trait] and lifetime bounds provide a way for [generic items][generic] to
2438
restrict which types and lifetimes are used as their parameters. Bounds can be
@@ -227,20 +241,26 @@ trait Trait<'a, T: 'a> {}
227241
impl<'a, T> Trait<'a, T> for &'a T {}
228242
```
229243

244+
## Use bounds
245+
246+
Certain bounds lists may include a `use<..>` bound to control which generic parameters are captured by the `impl Trait` [abstract return type]. See [precise capturing] for more details.
230247

248+
[IDENTIFIER]: identifiers.html
231249
[LIFETIME_OR_LABEL]: tokens.md#lifetimes-and-loop-labels
232250
[_GenericParams_]: items/generics.md
233251
[_TypePath_]: paths.md#paths-in-types
234252
[`Clone`]: special-types-and-traits.md#clone
235253
[`Copy`]: special-types-and-traits.md#copy
236254
[`Sized`]: special-types-and-traits.md#sized
237255

256+
[abstract return type]: types/impl-trait.md#abstract-return-types
238257
[arrays]: types/array.md
239258
[associated types]: items/associated-items.md#associated-types
240259
[hrtb-scopes]: names/scopes.md#higher-ranked-trait-bound-scopes
241260
[supertraits]: items/traits.md#supertraits
242261
[generic]: items/generics.md
243262
[higher-ranked lifetimes]: #higher-ranked-trait-bounds
263+
[precise capturing]: types/impl-trait.md#precise-capturing
244264
[slice]: types/slice.md
245265
[Trait]: items/traits.md#trait-bounds
246266
[trait object]: types/trait-object.md

src/types/impl-trait.md

+30-3
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,33 @@ Functions in traits may also use `impl Trait` as a syntax for an anonymous assoc
9191

9292
Every `impl Trait` in the return type of an associated function in a trait is desugared to an anonymous associated type. The return type that appears in the implementation's function signature is used to determine the value of the associated type.
9393

94-
### Differences between generics and `impl Trait` in return position
94+
## Capturing
95+
96+
Behind each return-position `impl Trait` abstract return type is some hidden concrete type. For this concrete type to use a generic parameter, that generic parameter must be *captured* by the abstract type.
97+
98+
## Automatic capturing
99+
100+
Return-position `impl Trait` abstract return types automatically capture certain of the in-scope generic parameters. Everywhere, these automatically capture all in-scope type and const generic parameters.
101+
102+
On items of trait impls and trait definitions, these types additionally automatically capture all in-scope generic lifetime parameters, including higher-ranked ones.
103+
104+
## Precise capturing
105+
106+
The set of generic parameters captured by a return-position `impl Trait` abstract type may be explicitly controlled with a [`use<..>` bound]. If present, only the generic parameters listed in the bound will be captured. E.g.:
107+
108+
```rust
109+
fn capture<'a, 'b, T>(x: &'a (), y: T) -> impl Sized + use<'a, T> {
110+
// ~~~~~~~~~~~~~~~~~~~~~~~
111+
// Captures `'a` and `T` only.
112+
(x, y)
113+
}
114+
```
115+
116+
Currently, only one `use<..>` bound may be present in a bounds list, such bounds are not allowed in the signature of items of a trait definition, and all in-scope type and const generic parameters must be included. If the elided lifetime (`'_`) is otherwise allowed to appear within the `impl Trait` return type, it may be named within the `use<..>` bound.
117+
118+
Because all in-scope type parameters must be included by name, a `use<..>` bound may not be used in the signature of items that use argument-position `impl Trait`, as those items have anonymous type parameters in scope.
119+
120+
## Differences between generics and `impl Trait` in return position
95121

96122
In argument position, `impl Trait` is very similar in semantics to a generic type parameter.
97123
However, there are significant differences between the two in return position.
@@ -127,9 +153,10 @@ Instead, the function chooses the return type, but only promises that it will im
127153
`impl Trait` can only appear as a parameter or return type of a non-`extern` function.
128154
It cannot be the type of a `let` binding, field type, or appear inside a type alias.
129155

130-
[closures]: closure.md
131156
[_GenericArgs_]: ../paths.md#paths-in-expressions
132157
[_GenericParams_]: ../items/generics.md
133158
[_TraitBound_]: ../trait-bounds.md
134-
[trait object]: trait-object.md
135159
[_TypeParamBounds_]: ../trait-bounds.md
160+
[`use<..>` bound]: ../trait-bounds.md#use-bounds
161+
[closures]: closure.md
162+
[trait object]: trait-object.md

0 commit comments

Comments
 (0)