TAIT captures lifetime that it shouldn't capture

⚓ Rust    📅 2025-12-08    👤 surdeus    👁️ 1      

surdeus

Hi, code like this gives an error (playground):

#![feature(type_alias_impl_trait)]

trait Foo {
    type Bar: 'static;
}

type Bar = impl Sized + 'static;

impl<'a> Foo for &'a () {
    type Bar = ();
}

#[define_opaque(Bar)]
fn foo<'a>(unit: &'a ()) -> impl Foo<Bar = Bar> + use<'a> {
    bar(unit)
}

fn bar<'a>(unit: &'a ()) -> impl Foo {
    unit
}

fn main() {}

Error:

 error[E0700]: hidden type for `Bar` captures lifetime that does not appear in bounds
   --> src/main.rs:15:5
    |
  7 | type Bar = impl Sized + 'static;
    |            -------------------- opaque type defined here
 ...
 14 | fn foo<'a>(unit: &'a ()) -> impl Foo<Bar = Bar> + use<'a> {
    |        -- hidden type `<impl Foo as Foo>::Bar` captures the lifetime `'a` as defined here
 15 |     bar(unit)
    |     ^^^^^^^^^

 For more information about this error, try `rustc --explain E0700`.
 error: could not compile `play` (bin "play") due to 1 previous error

While code like this compiles:

#![feature(type_alias_impl_trait)]

trait Foo {
    type Bar: 'static;
}

type Bar = impl Sized + 'static;

impl<'a> Foo for &'a () {
    type Bar = ();
}

#[define_opaque(Bar)]
fn foo<'a>(unit: &'a ()) -> impl Foo<Bar = Bar> + use<'a> {
    unit
}

fn main() {}

In both cases Bar should be resolved to the same value. Additionally borrow checker must have a hint that Bar can't capture anything, as it will not be well-formed without 'static. Is there some way I can somehow spell that bar will not have Bar capturing from 'a? So the code compiles.

Making Bar generic over a lifetime will not pass further checks for 'static in real code, it is in where bounds.

1 post - 1 participant

Read full topic

🏷️ Rust_feed