dtolnay / async-trait

Type erasure for async trait methods

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

`higher-ranked lifetime error` with a simple example involving a BTreeMap

cpgddln opened this issue · comments

The following (playground)

#[async_trait::async_trait]
trait T {
    async fn f(&self);
}
#[async_trait::async_trait]
// Compiles when the BTreeMap is replaced by a HashMap
impl T for BTreeMap<u32, Box<dyn Send + Sync + 'static>> {
    async fn f(&self) {
        for a in self {
            test().await;
        }
    }
}
async fn test() {}

results in

error: higher-ranked lifetime error
  --> src/lib.rs:11:23
   |
11 |       async fn f(&self) {
   |  _______________________^
12 | |         for a in self {
13 | |             test().await;
14 | |         }
15 | |     }
   | |_____^
   |
   = note: could not prove `for<'r, 's, 't0, 't1, 't2> Pin<Box<impl for<'r, 's, 't0, 't1> Future<Output = ()>>>: CoerceUnsized<Pin<Box<(dyn Future<Output = ()> + Send + 't2)>>>`

however, it works fine when the BTreeMap is replaced by a HashMap.
Might that be an issue with async_trait, or something I misunderstood?

Seems like a standard library bug.

Minimized:

//use std::collections::HashMap as Map;
use std::collections::BTreeMap as Map;

fn assert_send<T: Send>(_: T) {}

fn main() {
    assert_send(async {
        let map = Map::<u32, Box<dyn Send + Sync>>::new();
        let _iter = map.iter();
        async {}.await;
    });
}

Apparently this is rust-lang/rust#64552.

Thanks a lot for identifying the root cause in the standard library and even fixing it there, that's awesome!