Skip to content

Commit fcacb13

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.
1 parent 8c789ff commit fcacb13

File tree

3 files changed

+53
-5
lines changed

3 files changed

+53
-5
lines changed

src/names/scopes.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ type FnExample = for<'a> fn(x: Example<'a>) -> Example<'a>;
184184
#
185185
// The `impl Trait2` here is not allowed to refer to 'b but it is allowed to
186186
// refer to 'a.
187-
fn foo<'a>() -> impl for<'b> Trait1<Item = impl Trait2<'a>> {
187+
fn foo<'a>() -> impl for<'b> Trait1<Item = impl Trait2<'a> + use<'a>> {
188188
// ...
189189
# Example
190190
}

src/trait-bounds.md

+22-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,21 @@
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_ \
35+
> &nbsp;&nbsp; | [IDENTIFIER][] \
36+
> &nbsp;&nbsp; | `Self`
2237
2338
[Trait] and lifetime bounds provide a way for [generic items][generic] to
2439
restrict which types and lifetimes are used as their parameters. Bounds can be
@@ -227,20 +242,26 @@ trait Trait<'a, T: 'a> {}
227242
impl<'a, T> Trait<'a, T> for &'a T {}
228243
```
229244

245+
## Use bounds
246+
247+
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.
230248

249+
[IDENTIFIER]: identifiers.html
231250
[LIFETIME_OR_LABEL]: tokens.md#lifetimes-and-loop-labels
232251
[_GenericParams_]: items/generics.md
233252
[_TypePath_]: paths.md#paths-in-types
234253
[`Clone`]: special-types-and-traits.md#clone
235254
[`Copy`]: special-types-and-traits.md#copy
236255
[`Sized`]: special-types-and-traits.md#sized
237256

257+
[abstract return type]: types/impl-trait.md#abstract-return-types
238258
[arrays]: types/array.md
239259
[associated types]: items/associated-items.md#associated-types
240260
[hrtb-scopes]: names/scopes.md#higher-ranked-trait-bound-scopes
241261
[supertraits]: items/traits.md#supertraits
242262
[generic]: items/generics.md
243263
[higher-ranked lifetimes]: #higher-ranked-trait-bounds
264+
[precise capturing]: types/impl-trait.md#precise-capturing
244265
[slice]: types/slice.md
245266
[Trait]: items/traits.md#trait-bounds
246267
[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 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 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. On free functions and on associated functions and methods of inherent impls, only the generic lifetime parameters that appear in the bounds of abstract return type are captured.
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 `use<..>` 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, all in-scope type and const generic parameters must be included, and all lifetime parameters that appear in other bounds of the abstract type must be included. Within the `use<..>` bound, any lifetime parameters present must appear before all type and const generic parameters, and the elided lifetime (`'_`) may be present if it is otherwise allowed to appear within the `impl Trait` return type.
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)