what is impl Trait + 'lifetime

740 Views Asked by At

I am reading the async book. In section async lifetimes there is a code snippet whose grammar I am not familiar with:

fn foo_expanded<'a>(x: &'a u8) -> impl Future<Output = u8> + 'a {
    async move { *x }
}

In impl Future<Output = u8> + 'a, what is impl Trait + 'lifetime here?

Update: I am more asking what it is instead of the lifetime logic explanation. A definition from the official doc will be much appreciated.

2

There are 2 best solutions below

0
On BEST ANSWER

what is impl Trait + 'lifetime here?

It is an Impl trait, here particularly used as an abstract return type

Impl trait

Syntax

ImplTraitType : impl TypeParamBounds
ImplTraitTypeOneBound : impl TraitBound

impl Trait provides ways to specify unnamed but concrete types that implement a specific trait. It can appear in two sorts of places: argument position (where it can act as an anonymous type parameter to functions), and return position (where it can act as an abstract return type).

trait Trait {}

// argument position: anonymous type parameter
fn foo(arg: impl Trait) {
}

// return position: abstract return type
fn bar() -> impl Trait {
}

Where the grammar of TypeParamBounds allows both trait and lifetime bounds

Trait and lifetime bounds

Syntax

TypeParamBounds :
   TypeParamBound ( + TypeParamBound )* +?

TypeParamBound :
      Lifetime | TraitBound

TraitBound :
      ?? ForLifetimes? TypePath
   | ( ?? ForLifetimes? TypePath )

LifetimeBounds :
   ( Lifetime + )* Lifetime?

Lifetime :
      LIFETIME_OR_LABEL
   | 'static
   | '_

Particularly noting that the grammar of TypeParamBounds is one or optionally several TypeParamBounds combined, each of which in turn is either TraitBound or Lifetime (bounds).

Specifying Multiple Trait Bounds with the + Syntax describe in some detail that we may combine more than one trait bound, but the same applies for lifetime bounds (where the grammar allows it). One could argue that the section should also mention lifetime bounds.

1
On

Not entirely familiar, but logically it makes sense:

The function returns a Future that, when completed returns a byte. When the async fn is actually executed, it moves x, which is a reference with a lifetime. Technically x could be dropped before the Future is completed. To prevent this the lifetime trait guarantees that the return value of the function lives at least as long as x