Incorrect lifetime bound check in async + impl_trait_in_assoc_type · Issue #114572 · rust-lang/rust (original) (raw)

I tried this code:

#![feature(type_alias_impl_trait)] #![feature(impl_trait_in_assoc_type)]

use std::{fmt::Display, future::Future};

pub trait SharedDisplay: Display + Send + 'static {}

pub struct Message<T: AsRef> { inner: T, }

pub trait AsyncPrinter: Send + Sync { type AsyncOutput<'a>: Future<Output = String> + Send where Self: 'a;

fn to_string(&self, msg: Message<Box<dyn SharedDisplay>>) -> Self::AsyncOutput<'_>;

}

struct FooPrinter;

impl AsyncPrinter for FooPrinter { type AsyncOutput<'a> = impl Future<Output = String> + Send + 'a where Self: 'a;

fn to_string(&self, msg: Message<Box<dyn SharedDisplay>>) -> Self::AsyncOutput<'_> {
    async move { msg.inner.to_string() }
}

}

I expected to see this happen: The code correctly compiles

Instead, this happened: The code fails to compile with lifetime bound check errors.

More information that might be helpful

I did a bisect and found that the above code compiles in nightly-2023-03-14 but fails in nightly-2023-03-15, possibly due to #108909 but I didn't dig deep to find the root cause.

Also, by changing the implementation of the to_string function of FooPrinter by wrapping the async block with a smart pointer (see below), the code successfully compiles

fn to_string(&self, msg: Message<Box>) -> Self::AsyncOutput<'_> { Box::pin(async move { msg.inner.to_string() }) }

Let me know if more info is needed, or actually my codes fails to compile by design.

Meta

rustc --version --verbose:

rustc 1.73.0-nightly (474709a9a 2023-08-03)
binary: rustc
commit-hash: 474709a9a2a74a8bcf0055fadb335d0ca0d2d939
commit-date: 2023-08-03
host: x86_64-apple-darwin
release: 1.73.0-nightly
LLVM version: 16.0.5

Backtrace

error[E0478]: lifetime bound not satisfied
  --> src/lib.rs:23:28
   |
23 |     type AsyncOutput<'a> = impl Future<Output = String> + Send + 'a where Self: 'a;
   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
note: lifetime parameter instantiated with the lifetime `'a` as defined here
  --> src/lib.rs:23:22
   |
23 |     type AsyncOutput<'a> = impl Future<Output = String> + Send + 'a where Self: 'a;
   |                      ^^
   = note: but lifetime parameter must outlive the static lifetime