GATs in where-clauses
🚨 Warning: Speculation ahead. This is the "shiny future" page that integrates various speculative features. To see how things work today, see the corresponding page on the explainer.
Now that we have defined an Iterable
trait, we can explore different ways to reference it.
Specifying the value of a GAT
Given some type T: Clone
, this function takes any Iterable
that yields &T
references, clones them, and returns a vector of the resulting T
values:
Let's look at this function more closely. The most interesting part is the type of the iterable
parameter:
Both '_
and &T
-with-no-explicit-lifetime are examples of Rust's "lifetime elision" syntax. You're probably familiar with elision from functions like this one:
Whenever lifetimes are elided in input position, it means "pick any lifetime, I don't care". When they are elided in output position, it means "pick a lifetime from the inputs, or error if that's ambiguous". For functions, you can use a named lifetime to make the connection more explicit:
In the same way, with GATs, we can use a named lifetime, bound with for
, to make things more explicit:
The for
notation here is meant to read like "for any lifetime 'c
, Item<'c>
will be &'c T
".
Applying GATs to a specific lifetime
The previous example showed an iterable applied to any lifetime. It is also possible to give bounds for some specific lifetime. This function, for example, takes an iterable
with lifetime 'i
and yields up the first element:
The bound impl Iterable<Item<'i> = &'i T>
says "when iterated with lifetime 'i
, the resulting reference is &'i T
".
Bounding a GAT
Sometimes we want to specify that the value of a GAT meets some additional trait bound. For example, maybe wish to accept any Iterable
, so long as its Item
values implement Send
. The '_
notation we saw earlier can be used to do that quite easily:
Using another nightly feature (associated_type_bounds
, tracked in #52662), you can also write the above more compactly: