Skip to content

Commit a7a54f5

Browse files
committed
Add explanation for required clauses on GATs
1 parent 1ef107a commit a7a54f5

File tree

1 file changed

+62
-0
lines changed

1 file changed

+62
-0
lines changed

src/items/associated-items.md

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,68 @@ impl<T> Container for Vec<T> {
335335
}
336336
```
337337

338+
### Required where clauses on generic associated types
339+
340+
Generic associated type declarations on traits currently may require a list of
341+
where clauses, dependent on functions in the trait and how the GAT is used.
342+
343+
In a few words, these where clauses are required in order to maximize the allowed
344+
definitions of the associated type in impls. To do this, any clauses that *can be
345+
proven to hold* on functions (using the parameters of the function or trait)
346+
where a GAT appears as an input or output must also be written on the GAT itself.
347+
348+
```rust
349+
trait LendingIterator {
350+
type Item<'x> where Self: 'x;
351+
fn next<'a>(&'a mut self) -> Self::Item<'a>;
352+
}
353+
```
354+
355+
In the above, on the `next` function, we can prove that `Self: 'a`, because of
356+
the implied bounds from `&'a mut self`; therefore, we must write the equivalent
357+
bound on the GAT itself: `where Self: 'x`.
358+
359+
When there are multiple functions in a trait that use the GAT, then the
360+
*intersection* of the bounds from the different functions are used, rather than
361+
the union.
362+
363+
```rust
364+
trait Check<T> {
365+
type Checker<'x>;
366+
fn create_checker<'a>(item: &'a T) -> Self::Checker<'a>;
367+
fn do_check(checker: Self::Checker<'a>);
368+
}
369+
```
370+
371+
In this example, no bounds are required on the `type Checker<'a>;`. While we
372+
know that `T: 'a` on `create_checker`, we do not know that on `do_check`. However,
373+
if `do_check` was commented out, then the `where T: 'x` bound would be required
374+
on `Checker`.
375+
376+
The bounds on associated types also propagate required where clauses.
377+
378+
```rust
379+
trait Iterable {
380+
type Item<'a> where Self: 'a;
381+
type Iterator<'a>: Iterator<Item = Self::Item<'a>> where Self: 'a;
382+
fn iter<'a>(&'a self) -> Self::Iterator<'a>;
383+
}
384+
```
385+
386+
Here, `where Self: 'a` is required on `Item` because of `iter`. However, `Item`
387+
is used in the bounds of `Iterator`, the `where Self: 'a` clause is also required
388+
there.
389+
390+
Finally, any explicit uses of `'static` on GATs in the trait do not count towards
391+
the required bounds.
392+
393+
```rust
394+
trait StaticReturn {
395+
type Y<'a>;
396+
fn foo(&self) -> Self::Y<'static>;
397+
}
398+
```
399+
338400
## Associated Constants
339401

340402
*Associated constants* are [constants] associated with a type.

0 commit comments

Comments
 (0)