Repository: rust
Issue: GATs: Decide whether to have defaults for `where Self: 'a`
Labels: T-lang,disposition-merge,finished-final-comment-period,GATs-triaged,T-types,A-GATs

## Coming from the "missing required bounds" error?

The "missing required bounds" error that was emitted is intended to ensure that current code is forwards-compatible with potential future changes. We'll provide a brief summary of the why the bounds are required, the potential future changes, and a workaround if the required bounds are too restrictive. We would appreciate any feedback for this issue.

### Why are these bounds required

Let's start by imagining a trait:

```rust
trait Iterable {
    type Item<'x>;
    fn iter<'a>(&'a self) -> Self::Item<'a>;
}
```

As-is, nothing looks wrong about this; without the "missing required bounds" error, this would compile. However, let's try to add an impl:

```rust
impl<T> Iterable for T {
    type Item<'a> = &'a T;
    fn iter<'a>(&'a self) -> Self::Item<'a> { self }
}
```

This definition of `Item<'a> = &'a T` is invalid, since we don't know that `T` outlives `'a`. So, our first thought might be to modify the definition to add a `where Self: 'a` clause. This is what we *want*. However, impls are not allowed to have more where clauses than the trait.

Luckily, we can detect in a trait when this type of problem might occur. To do this, we look at the trait methods that *construct* the GAT. There, we find the bounds that *we know* and require that those bounds be written on the GAT itself.

Here, on the `Iterable` trait, we construct the GAT `Self::Item<'a>` in the `iter` method. There, we have an argument `&'a self`, which allows us to know `Self: 'a`. Therefore, we require the `where Self: 'a` bound on the GAT.

### Potential future changes

Following the above logic, if we know all the required bounds when the trait is written, *why require them at all*? In fact, allowed these bounds to be *implied* is a potential future change. However, to make this change in a backwards-compatible manner, we must require the bounds now that we want to eventually imply. At that time, the written bounds will be redundant and can be removed.

### This breaks my code. Workaround?

First, if any code breaks from adding the required bounds, we *really* want feedback. Second, the workaround is to move the GAT into a super trait. Using the example above, our new code would look like:

```rust
trait IterableSuper {
    type Item<'x>;
}
trait Iterable: IterableSuper {
    fn iter<'a>(&'a self) -> Self::Item<'a>;
}
```

## Previous discussion

### What is this bug?

We are moving towards stabilizing GATs (tracking issue: https://github.com/rust-lang/rust/issues/44265) but there is one major ergonomic hurdle that we should decide how to manage before we go forward. In particular, a great many GAT use cases require a surprising where clause to be well-typed; this typically has the form `where Self: 'a`. It might be useful if we were to create some rules to add this rule by default. Once we stabilize, changing defaults will be more difficult, and could require an edition, therefore it's better to evaluate the rules now.

### I have an opinion! What should I do?

To make this decision in an informed way, **what we need most are real-world examples and experience reports**. If you are experimenting with GATs, for example, how often do you use `where Self: 'a` and how did you find out that it is necessary? Would the default proposals described below work for you? If not, can you describe the trait so we can understand why they would not work?

Of great use would be example usages that do NOT require `where Self: 'a`. It'd be good to be able to evaluate the various defaulting schemes and see whether they would interfere with the trait. Knowing the trait and a rough sketch of the impls would be helpful.
### Background: what where clause now?

Consider the typical "lending iterator" example. The idea here is to have an iterator that produces values that may have references into the **iterator itself** (as opposed to references into the collection being iterated over). In other words, given a `next` method like `fn next<'a>(&'a mut self)`, the returned items have to be able to reference `'a`. The typical `Iterator` trait cannot express that, but GATs can:

```rust
trait LendingIterator {
    type Item<'a>;

    fn next<'b>(&'b mut self) -> Self::Item<'b>;
}
```

Unfortunately, this trait definition turns out to be not quite right in practice. Consider an example like this, an iterator that yields a reference to the same item over and over again (note that it owns the item it is referencing):

```rust
struct RefOnce<T> {
    my_data: T    
}

impl<T> LendingIterator for RefOnce<T> {
    type Item<'a> where Self: 'a = &'a T;

    fn next<'b>(&'b mut self) -> Self::Item<'b> {
        &self.my_data
    }
}
```

Here, the type `type Item<'a> = &'a T` declaration is actually illegal. Why is that? The assumption when authoring the trait was that `'a` would always be the lifetime of the `self` reference in the `next` function, of course, but that is not in fact *required*. People can reference `Item` with any lifetime they want. For example, what if somebody wrote the type `<SomeType<T> as LendingIterator>::Item<'static>`? In this case, `T: 'static` would have to be true, but `T` may in fact contain borrowed references. This is why the compiler gives you a "T may not outlive `'a`" error ([playground](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=821e30ee635326a22fc19cd940bbaf62)). 

We can encode the constraint that "`'a` is meant to be the lifetime of the `self` reference" by adding a `where Self: 'a` clause to the `type Item` declaration. This is saying "you can only use a `'a` that could be a reference to `Self`". If you make this change, you'll find that the code compiles ([playground](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=87cb2430ee76ece77499d3c6605874df)): 

```rust
trait LendingIterator {
    type Item<'a> where Self: 'a;

    fn next<'b>(&'b mut self) -> Self::Item<'b>;
}
```

### When would you NOT want the where clause `Self: 'a`?

If the associated type cannot refer to data that comes from the `Self` type, then the `where Self: 'a` is unnecessary, and is in fact somewhat constraining. As an example, consider:

XXX finish this

### What could we do about it?

There are a few options. Here is the list of ideas we've had so far.

1. Status quo: require that people add the `where Self: 'a` bounds, and try to do better with diagnostics.
2. Simple, limited default: If a GAT has exactly one lifetime parameter `'a`, add `where Self: 'a` to both traits and impls. Need some way to opt out.
3. More extensive defaults: e.g., for *every* lifetime parameter `'a` to a GAT, add `where Self: 'a`, and maybe `where T: 'a` for type parameters too. Need some way to opt out.
4. Add a syntactic sugar for this common case, e.g. `type Foo<'self>`. This could be added later.
5. self-oriented defaults: Given some GAT `Foo<'a>`, if each use `Self::Foo<'b>` within the trait methods references a `'b` that is the lifetime parameter for `self`, then add `where Self: 'b`. While kind of complex to explain, this captures the intuition that `'a` is meant to be the "lifetime of the self reference" in practice. We probably *still* want a way to opt out (though maybe not; maybe that way is "don't use `&'a self` notation").
6. Even smarter defaults A: Look at the method signatures in the trait. If we find that each use of `Self::Item<'b>` is associated with a lifetime `'b` where `Self: 'b` is implied by the method arguments, *then* infer that `where Self: 'b`. This is a more extensive, general version of *self-oriented defaults*. We probably *still* want a way to opt out (though maybe not).

In general, once we stabilize GATs, we likely cannot add defaults, except via an edition -- although we may be able to get away with it in this instance if the defaults are smart enough.