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 Area: impl Trait. Universally / existentially quantified anonymous types with static dispatch. A-lifetimes Area: lifetime related C-enhancement Category: An issue proposing an enhancement or a PR with one. T-lang Relevant to the language team, which will review and decide on the PR/issue.

Comments

@oxalica
Copy link
Contributor

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 Area: impl Trait. Universally / existentially quantified anonymous types with static dispatch. A-lifetimes Area: lifetime related C-bug Category: This is a bug. T-lang Relevant to the language team, which will review and decide on the PR/issue. C-enhancement Category: An issue proposing an enhancement or a PR with one. and removed C-bug Category: This is a bug. labels Nov 19, 2019
@kennytm
Copy link
Member

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
Member

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 Area: impl Trait. Universally / existentially quantified anonymous types with static dispatch. A-lifetimes Area: lifetime related C-enhancement Category: An issue proposing an enhancement or a PR with one. T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

4 participants