Repository: rust
Issue: associated types are unnameable when traits implemented on references
Labels: A-lifetimes,A-associated-items,T-lang,C-bug,T-types

[playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=0f564befebb658d7e6ce84efa3f7c2f7)

Consider this pattern where I have something that dereferences to an iterator, and I want to hold a container of the iterator's `Item` type next to it. The `Item` type is `'static`.

```rust
struct CollectingIterator<'a, S>
where
    S: std::ops::Deref,
    &'a S::Target: IntoIterator,
{
    s: S,
    acc: std::collections::HashSet<<&'a S::Target as IntoIterator>::Item>,
}

impl<'a, S> CollectingIterator<'a, S>
where
    S: std::ops::Deref,
    &'a S::Target: IntoIterator,
    <&'a S::Target as IntoIterator>::Item: Eq + std::hash::Hash + Copy,
{
    fn collect(&mut self) -> Vec<<&'a S::Target as IntoIterator>::Item> {
        use std::iter::Extend as _;

        let Self { s, acc } = self;
        let ret: Vec<_> = (&*s).into_iter().collect();
        acc.extend(ret.iter().copied());
        ret
    }
}

fn takes_bytes<const N: usize>(bytes: [u8; N]) {
    let mut i = CollectingIterator {
        s: std::rc::Rc::new(bytes),
        acc: Default::default(),
    };
    println!("{:?}", i.collect())
}

fn main() {}
```

this doesn't compile because the lifetime `'a` isn't what I want:

```
error: lifetime may not live long enough
  --> src/main.rs:20:27
   |
10 | impl<'a, S> CollectingIterator<'a, S>
   |      -- lifetime `'a` defined here
...
16 |     fn collect(&mut self) -> Vec<<&'a S::Target as IntoIterator>::Item> {
   |                - let's call the lifetime of this reference `'1`
...
20 |         let ret: Vec<_> = (&*s).into_iter().collect();
   |                           ^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'a`
```

What I want instead is to use a higher kinded lifetime:

[playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=e116a7d40fae535064b064268cc1d3a0)

```diff
-struct CollectingIterator<'a, S>
+struct CollectingIterator<S>
 where
     S: std::ops::Deref,
-    &'a S::Target: IntoIterator,
+    for<'a> &'a S::Target: IntoIterator,
 {
     s: S,
     acc: std::collections::HashSet<<&'a S::Target as IntoIterator>::Item>,
 }
 
-impl<'a, S> CollectingIterator<'a, S>
+impl<S> CollectingIterator<S>
 where
     S: std::ops::Deref,
-    &'a S::Target: IntoIterator,
-    <&'a S::Target as IntoIterator>::Item: Eq + std::hash::Hash + Copy,
+    for<'a> &'a S::Target: IntoIterator,
+    for<'a> <&'a S::Target as IntoIterator>::Item: Eq + std::hash::Hash + Copy,
 {
-    fn collect(&mut self) -> Vec<<&'a S::Target as IntoIterator>::Item> {
+    fn collect(&mut self) -> Vec<<&S::Target as IntoIterator>::Item> {
         use std::iter::Extend as _;
 
         let Self { s, acc } = self;
```

This doesn't work because `'a ` is undeclared:
```
error[[E0261]](https://doc.rust-lang.org/stable/error_codes/E0261.html): use of undeclared lifetime name `'a`
 --> src/main.rs:7:38
  |
1 | struct CollectingIterator<S>
  |                           - help: consider introducing lifetime `'a` here: `'a,`
...
7 |     acc: std::collections::HashSet<<&'a S::Target as IntoIterator>::Item>,
  |                                      ^^ undeclared lifetime
```
but how to declare it? I can't use an HKT there:
```diff
     for<'a> &'a S::Target: IntoIterator,
 {
     s: S,
-    acc: std::collections::HashSet<<&'a S::Target as IntoIterator>::Item>,
+    acc: std::collections::HashSet<<for<'a> &'a S::Target as IntoIterator>::Item>,
 }
 
 impl<S> CollectingIterator<S>
```
because that's not valid syntax:
```
error: expected `while`, `for`, `loop` or `{` after a label
 --> src/main.rs:7:49
  |
7 |     acc: std::collections::HashSet<<for<'a> &'a S::Target as IntoIterator>::Item>,
  |                                                 ^ expected `while`, `for`, `loop` or `{` after a label

error: expected identifier, found `&`
```

which means all I can do is `'static`:

```diff
     for<'a> &'a S::Target: IntoIterator,
 {
     s: S,
-    acc: std::collections::HashSet<<for<'a> &'a S::Target as IntoIterator>::Item>,
+    acc: std::collections::HashSet<<&'static S::Target as IntoIterator>::Item>,
 }
 
 impl<S> CollectingIterator<S>

```

but that imposes other restrictions which I don't want:

```
error[[E0310]](https://doc.rust-lang.org/stable/error_codes/E0310.html): the associated type `<S as Deref>::Target` may not live long enough
 --> src/main.rs:7:10
  |
7 |     acc: std::collections::HashSet<<&'static S::Target as IntoIterator>::Item>,
  |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = help: consider adding an explicit lifetime bound `<S as Deref>::Target: 'static`...
  = note: ...so that the reference type `&'static <S as Deref>::Target` does not outlive the data it points at
```

It seems to me that there's simply no way to express this.