Skip to content

Incorrect lifetime bound check in async + impl_trait_in_assoc_type #114572

Closed

Description

@xiaoyawei

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<dyn SharedDisplay>> {
    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<dyn SharedDisplay>>) -> 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

Activity

  1. added
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    on Aug 7, 2023
  2. compiler-errors commented on Aug 8, 2023

    @compiler-errors
    Contributor

    This is impl_trait_in_assoc_type, not RPITIT. This doesn't have to do with #108909 -- I'll do a full bisection later.

  3. changed the title [-]Incorrect lifetime bound check in RPITIT[/-] [+]Incorrect lifetime bound check in async + impl_trait_in_assoc_type[/+] on Aug 8, 2023
  4. compiler-errors commented on Aug 8, 2023

    @compiler-errors
    Contributor

    searched nightlies: from nightly-2023-02-01 to nightly-2023-04-01
    regressed nightly: nightly-2023-03-15
    searched commit range: 22f247c...1716932
    regressed commit: 669e751

    bisected with cargo-bisect-rustc v0.6.5

    Host triple: aarch64-unknown-linux-gnu
    Reproduce with:

    cargo bisect-rustc --start=2023-02-01 --end=2023-04-01 --prompt 

    This regressed in #104833. Strange, but perhaps a case that #105300 didn't end up fixing? cc @aliemjay

  5. added
    WG-asyncWorking group: Async & await
    and removed
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    on Aug 8, 2023
  6. lqd commented on Aug 8, 2023

    @lqd
    Member

    Note for bisection, impl_trait_in_assoc_type was added a month after the expected nightly-2023-03-15 and points to #104833 locally.

    (dang, too slow)

  7. self-assigned this
    on Aug 8, 2023
  8. aliemjay commented on Aug 9, 2023

    @aliemjay
    Contributor

    Minimized:

    #![feature(type_alias_impl_trait)]
    struct Static<T: 'static>(T);
    type Output<'a> = impl Sized + 'a;
    fn relate<'a>(msg: Static<&'static u8>) -> Output<'a> {
        msg
    }

    The hidden type is inferred to be Output<'a> = Static<&'a str>, but that's not a well-formed type. This is not a problem for RPIT only because we skip the well-formedness check of the hidden type.

  9. added 2 commits that reference this issue on Feb 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

C-bugCategory: This is a bug.F-impl_trait_in_assoc_type`#![feature(impl_trait_in_assoc_type)]`F-type_alias_impl_trait`#[feature(type_alias_impl_trait)]`WG-asyncWorking group: Async & await

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions