rust-lang/futures-rs

“expected bound lifetime parameter, found concrete lifetime” with `'static` across await point

Ekleog opened this issue · 5 comments

ISSUE MOVED TO rust-lang/rust#53548

(edit: simpler reproducer without channels at #1199 (comment))

On the currently-latest commit of futures-rs (c02ec75), with the currently-latest nightly (2018-08-14), the following code does not build:

#![feature(async_await, await_macro, futures_api)]

extern crate futures;

use futures::{channel::mpsc::{self, SendError}, prelude::*};
use std::any::Any;

async fn send(msg: Box<Any + Send + 'static>) -> Result<(), SendError> {
    let (mut sender, _) = mpsc::channel(1);
    await!(sender.send(msg))
}

It fails with the following error:

error[E0279]: the requirement `for<'r> 'r : 'static` is not satisfied (`expected bound lifetime parameter, found concrete lifetime`)
  --> erlust/src/lib.rs:8:72
   |
8  |   async fn send(msg: Box<Any + Send + 'static>) -> Result<(), SendError> {
   |  ________________________________________________________________________^
9  | |     let (mut sender, _) = mpsc::channel(1);
10 | |     await!(sender.send(msg))
11 | | }
   | |_^
   |
   = note: required so that the lifetime bound of `` for `dyn std::any::Any + std::marker::Send` is satisfied

error: aborting due to previous error

I can't figure out the reason why it fails, so I'm assuming it's something in futures-rs. But maybe it's actually a rustc bug from async/await? Or maybe it's just me missing something obvious, actually :)

Just found another simpler reproducer: same version of futures-rs (c02ec75), same nightly (2018-08-14), this code fails to build with “the requirement for<'r> 'r : 'static is not satisfied”:

#![feature(async_await, await_macro, futures_api)]

use futures::future;                                  
                                                      
use std::any::Any;                                    
                                                      
async fn send(msg: Box<Any + Send + 'static>) -> () { 
    await!(future::lazy(move |_| {                    
        msg;                                          
        ()                                            
    }))                                               
}                                                     

Now I'm thinking this is likely a problem in rustc, so cc'ing rust-lang/rust#50547

Also, it reproduces only when the Any bound is present, having only Send + 'static is not enough to trigger the issue.

It looks like this is an issue specific to async/await: when I have this, it reproduces (playground link)

#![feature(generators, async_await, futures_api)]

use std::any::Any;

async fn send(msg: Box<Any + 'static>) -> () {
    let mut pinned = move || { msg; () };
    yield
}

(interestingly, with Send or a custom trait like trait Trait {} instead of Any, the error doesn't arise)

But with this (trying to reproduce with generators only), it compiles as expected: (playground link)

#![feature(generators, generator_trait)]

use std::any::Any;
use std::ops::Generator;

fn send(msg: Box<Any + 'static>) -> impl Generator + 'static {
    || {
        let mut pinned = move || { msg; () };
        yield
    }
}

The specificity of Any in the above example appears to be due to its having a 'static bound: this compiles (playground):

#![feature(generators, async_await, futures_api)]

use std::any::Any;

trait Trait {}

async fn send(msg: Box<Trait + 'static>) -> () {
    let mut pinned = move || { msg; () };
    yield
}

And this does not: (playground)

#![feature(generators, async_await, futures_api)]

use std::any::Any;

trait Trait: 'static {}

async fn send(msg: Box<Trait + 'static>) -> () {
    let mut pinned = move || { msg; () };
    yield
}

Closing for moving this issue to rust-lang/rust#53548.