Repository: rust
Issue: Generators generating wrong lifetimes
Labels: A-lifetimes,T-compiler,C-bug,E-needs-mcve,T-types

I'm pretty sure something like that has already been reported, maybe about HRTB, but I can't find an exact issue.

I tried this code:

```rust
use std::{cmp::Eq, collections::HashMap, hash::Hash, sync::Arc, time::Duration, future::Future};

use tokio::{sync::RwLock, time::sleep};

/// This struct works as an async barrier like OnceCell, but locks disappear from memory after a given time, and there are different callbacks for read and write
pub struct OnceBarrier<T>
where T: Hash + Eq + Clone + Send + Sync + 'static {
    delay: Duration,
    inner: Arc<RwLock<HashMap<T, Arc<RwLock<()>>>>>,
}

impl<T> OnceBarrier<T>
where T: Hash + Eq + Clone + Send + Sync + 'static {
    pub fn new(delay: Duration) -> Self {
        OnceBarrier {
            delay,
            inner: Arc::new(RwLock::new(HashMap::new())),
        }
    }

    async fn can_read(&self, key: &T) -> bool {
        let lock = self.inner.read().await;
        if let Some(rw) = lock.get(key) {
            rw.read().await;
            true
        }
        else {
            false
        }
    }

    pub async fn get<Read, ReadFut, Write, WriteFut, Out>(&self, key: T, read_callback: Read, write_callback: Write) -> Out
    where
        Read: Fn(&T) -> ReadFut,
        ReadFut: Future<Output=Out>,
        Write: Fn(&T) -> WriteFut,
        WriteFut: Future<Output=Out>,
    {
        // check if entry exists
        if self.can_read(&key).await {
            return read_callback(&key).await;
        }

        // entry still doesn't exists
        let mut lock = self.inner.write().await;
        if lock.get(&key).is_some() {
            // we are late, drop write lock to dequeue and retry
            drop(lock);
            if self.can_read(&key).await {
                return read_callback(&key).await;
            }
            else {
                unreachable!();
            }
        }

        // create the entry and write-lock it
        let inner = Arc::new(RwLock::new(()));
        lock.insert(key.clone(), Arc::clone(&inner));
        let temp = inner.write().await;
        drop(lock);

        // call write callback
        let res = write_callback(&key).await;
        // delete the entry after given time
        let delay = self.delay;
        let inner = Arc::clone(&self.inner);
        tokio::spawn(async move {
            sleep(delay).await;
            let mut lock = inner.write().await;
            lock.remove(&key);
        });
        // free write lock and return
        drop(temp);
        res
    }
}

#[tokio::main]
async fn main() {
    let ob = OnceBarrier::new(Duration::from_secs(1));
    println!("{}", ob.get(String::from("foo"), |foo| async move { println!("read {}", foo); 1_u8 }, |foo| async move { println!("write {}", foo); 2_u8 }).await);
    println!("{}", ob.get(String::from("foo"), |foo| async move { println!("read {}", foo); 1_u8 }, |foo| async move { println!("write {}", foo); 2_u8 }).await);
}
```

I expected to see this happen:
everything should works fine, like it's sync counterpart:
```rust
use std::{cmp::Eq, collections::HashMap, hash::Hash, sync::Arc, time::Duration};

use std::{sync::RwLock, thread};

/// This struct works as an async barrier like OnceCell, but locks disappear from memory after a given time, and there are different callbacks for read and write
pub struct OnceBarrier<T>
where T: Hash + Eq + Clone + Send + Sync + 'static {
    delay: Duration,
    inner: Arc<RwLock<HashMap<T, Arc<RwLock<()>>>>>,
}

impl<T> OnceBarrier<T>
where T: Hash + Eq + Clone + Send + Sync + 'static {
    pub fn new(delay: Duration) -> Self {
        OnceBarrier {
            delay,
            inner: Arc::new(RwLock::new(HashMap::new())),
        }
    }

    fn can_read(&self, key: &T) -> bool {
        let lock = self.inner.read().unwrap();
        if let Some(rw) = lock.get(key) {
            rw.read().unwrap();
            true
        }
        else {
            false
        }
    }

    pub fn get<Read, Write, Out>(&self, key: T, read_callback: Read, write_callback: Write) -> Out
    where
        Read: Fn(&T) -> Out,
        Write: Fn(&T) -> Out,
    {
        // check if entry exists
        if self.can_read(&key) {
            return read_callback(&key);
        }

        // entry still doesn't exists
        let mut lock = self.inner.write().unwrap();
        if lock.get(&key).is_some() {
            // we are late, drop write lock to dequeue and retry
            drop(lock);
            if self.can_read(&key) {
                return read_callback(&key);
            }
            else {
                unreachable!();
            }
        }

        // create the entry and write-lock it
        let inner = Arc::new(RwLock::new(()));
        lock.insert(key.clone(), Arc::clone(&inner));
        let temp = inner.write().unwrap();
        drop(lock);

        // call write callback
        let res = write_callback(&key);
        // delete the entry after given time
        let delay = self.delay;
        let inner = Arc::clone(&self.inner);
        thread::spawn(move || {
            thread::sleep(delay);
            let mut lock = inner.write().unwrap();
            lock.remove(&key);
        });
        // free write lock and return
        drop(temp);
        res
    }
}

fn main() {
    let ob = OnceBarrier::new(Duration::from_secs(1));
    println!("{}", ob.get(String::from("foo"), |foo| { println!("read {}", foo); 1_u8 }, |foo| { println!("write {}", foo); 2_u8 }));
    println!("{}", ob.get(String::from("foo"), |foo| { println!("read {}", foo); 1_u8 }, |foo| { println!("write {}", foo); 2_u8 }));
}
```

Instead, this happened:
I get an error like
```
82 | ...rom("foo"), |foo| async move { println!("read {}", foo); 1_u8 }, |foo| async move { println!("write {}", foo); 2_u8 }).await);
   |                 ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2`
   |                 |  |
   |                 |  return type of closure `impl Future` contains a lifetime `'2`
   |                 has type `&'1 String`
```
Obviously I tried naming a lifetime for &T and giving it to the returned Future, making things worse