Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

impl Trait cannot work well with lifetime bounds #66551

Open
oxalica opened this issue Nov 19, 2019 · 2 comments
Open

impl Trait cannot work well with lifetime bounds #66551

oxalica opened this issue Nov 19, 2019 · 2 comments
Labels
A-impl-trait A-lifetimes C-enhancement T-lang

Comments

@oxalica
Copy link
Contributor

@oxalica oxalica commented Nov 19, 2019

Playground

pub struct S<'t>(usize, &'t str);

impl<'t> S<'t> {
    // error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
    pub fn foo<'s>(&'s mut self) -> impl FnMut() + 's {
        move || self.0 += 1
    }
}

fn main() {
    let mut s = S(0, "hello");
    s.foo()();
    println!("{}", s.0);
}

The self: &'s mut S<'t> implies 't: 's, so the signature should be correct. But compiler still complain that 't is captured but does not appear in impl bounds.

I checked the error description of E0700 and tried impl FnMut() + 's where 't: 's and impl FnMut() + 's + 't, while it still fails.

Note that when using dyn Trait as pub fn foo<'s>(&'s mut self) -> Box<dyn FnMut() + 's>, it compiles.

@jonas-schievink jonas-schievink added A-impl-trait A-lifetimes C-bug T-lang C-enhancement and removed C-bug labels Nov 19, 2019
@kennytm
Copy link
Member

@kennytm kennytm commented May 17, 2020

You could workaround using the Captures trait.

pub trait Captures<U: ?Sized> {}
impl<U: ?Sized, T: ?Sized> Captures<U> for T {}

impl<'t> S<'t> {
    pub fn foo(&mut self) -> impl FnMut() + Captures<&'t str> + '_ {
        move || self.0 += 1
    }
}

@Nadrieril
Copy link
Contributor

@Nadrieril Nadrieril commented Dec 17, 2020

Could the Captures trait make it into std so that rustc can suggest it? It's otherwise impossible to discover this trick but it's a very useful one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-impl-trait A-lifetimes C-enhancement T-lang
Projects
None yet
Development

No branches or pull requests

4 participants