diff --git a/src/names/scopes.md b/src/names/scopes.md index 58ee99b55..55ef159b4 100644 --- a/src/names/scopes.md +++ b/src/names/scopes.md @@ -184,7 +184,7 @@ type FnExample = for<'a> fn(x: Example<'a>) -> Example<'a>; # // The `impl Trait2` here is not allowed to refer to 'b but it is allowed to // refer to 'a. -fn foo<'a>() -> impl for<'b> Trait1> { +fn foo<'a>() -> impl for<'b> Trait1 + use<'a>> { // ... # Example } diff --git a/src/trait-bounds.md b/src/trait-bounds.md index 96a8f8ec1..019a2f7f0 100644 --- a/src/trait-bounds.md +++ b/src/trait-bounds.md @@ -5,7 +5,7 @@ >    _TypeParamBound_ ( `+` _TypeParamBound_ )\* `+`? > > _TypeParamBound_ :\ ->       _Lifetime_ | _TraitBound_ +>       _Lifetime_ | _TraitBound_ | _UseBound_ > > _TraitBound_ :\ >       `?`? @@ -19,6 +19,21 @@ > _Lifetime_ :\ >       [LIFETIME_OR_LABEL]\ >    | `'static` +> +> _UseBound_ :\ +>    `use` _UseBoundGenericArgs_ +> +> _UseBoundGenericArgs_ :\ +>       `<` `>` \ +>    | `<` \ +>       ( _UseBoundGenericArg_ `,`)\* \ +>       _UseBoundGenericArg_ `,`? \ +>       `>` +> +> _UseBoundGenericArg_ :\ +>       _Lifetime_ \ +>    | [IDENTIFIER][] \ +>    | `Self` [Trait] and lifetime bounds provide a way for [generic items][generic] to restrict which types and lifetimes are used as their parameters. Bounds can be @@ -227,7 +242,11 @@ trait Trait<'a, T: 'a> {} impl<'a, T> Trait<'a, T> for &'a T {} ``` +## Use bounds + +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. +[IDENTIFIER]: identifiers.html [LIFETIME_OR_LABEL]: tokens.md#lifetimes-and-loop-labels [_GenericParams_]: items/generics.md [_TypePath_]: paths.md#paths-in-types @@ -235,12 +254,14 @@ impl<'a, T> Trait<'a, T> for &'a T {} [`Copy`]: special-types-and-traits.md#copy [`Sized`]: special-types-and-traits.md#sized +[abstract return type]: types/impl-trait.md#abstract-return-types [arrays]: types/array.md [associated types]: items/associated-items.md#associated-types [hrtb-scopes]: names/scopes.md#higher-ranked-trait-bound-scopes [supertraits]: items/traits.md#supertraits [generic]: items/generics.md [higher-ranked lifetimes]: #higher-ranked-trait-bounds +[precise capturing]: types/impl-trait.md#precise-capturing [slice]: types/slice.md [Trait]: items/traits.md#trait-bounds [trait object]: types/trait-object.md diff --git a/src/types/impl-trait.md b/src/types/impl-trait.md index 026909832..7e99949cf 100644 --- a/src/types/impl-trait.md +++ b/src/types/impl-trait.md @@ -91,7 +91,33 @@ Functions in traits may also use `impl Trait` as a syntax for an anonymous assoc 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. -### Differences between generics and `impl Trait` in return position +## Capturing + +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. + +## Automatic capturing + +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. + +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. + +## Precise capturing + +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.: + +```rust +fn capture<'a, 'b, T>(x: &'a (), y: T) -> impl Sized + use<'a, T> { + // ~~~~~~~~~~~~~~~~~~~~~~~ + // Captures `'a` and `T` only. + (x, y) +} +``` + +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. + +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. + +## Differences between generics and `impl Trait` in return position In argument position, `impl Trait` is very similar in semantics to a generic type parameter. 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 `impl Trait` can only appear as a parameter or return type of a non-`extern` function. It cannot be the type of a `let` binding, field type, or appear inside a type alias. -[closures]: closure.md [_GenericArgs_]: ../paths.md#paths-in-expressions [_GenericParams_]: ../items/generics.md [_TraitBound_]: ../trait-bounds.md -[trait object]: trait-object.md [_TypeParamBounds_]: ../trait-bounds.md +[`use<..>` bound]: ../trait-bounds.md#use-bounds +[closures]: closure.md +[trait object]: trait-object.md