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

Incorrect lifetime inferred for closure #26937

Closed
diwic opened this issue Jul 10, 2015 · 3 comments
Closed

Incorrect lifetime inferred for closure #26937

diwic opened this issue Jul 10, 2015 · 3 comments
Labels
A-borrow-checker Area: The borrow checker A-closures Area: Closures (`|…| { … }`)

Comments

@diwic
Copy link
Contributor

diwic commented Jul 10, 2015

Example:

struct Z<'a> {
    q: &'a (FnMut(&str) + 'a)
}

impl<'a> Z<'a> {
    fn new(q: &'a (FnMut(&str) + 'a)) -> Z<'a> { Z { q: q }}
}

pub fn main() {
    let c = |s| { println!("{}", s); };
    Z::new(&c);
}

Fails with:

<anon>:12:16: 12:18 error: type mismatch resolving `for<'r> <[closure <anon>:11:17: 11:43] as core::ops::FnOnce<(&'r str,)>>::Output == ()`:
 expected bound lifetime parameter, found concrete lifetime [E0271]
<anon>:12         Z::new(&c);
                         ^~
<anon>:12:16: 12:18 help: see the detailed explanation for E0271
<anon>:12:16: 12:18 note: required for the cast to the object type `for<'r> core::ops::FnMut(&'r str)`
<anon>:12         Z::new(&c);
                         ^~
<anon>:12:16: 12:18 error: type mismatch: the type `[closure <anon>:11:17: 11:43]` implements the trait `core::ops::FnMut<(_,)>`, but the trait `for<'r> core::ops::FnMut<(&'r str,)>` is required (expected concrete lifetime, found bound lifetime parameter ) [E0281]
<anon>:12         Z::new(&c);
                         ^~
<anon>:12:16: 12:18 note: required for the cast to the object type `for<'r> core::ops::FnMut(&'r str)`
<anon>:12         Z::new(&c);
                         ^~

The problem can be worked around by writing |s: &str| instead of just |s|, but according to @eddyb this behaviour should be improved to infer the correct lifetime.

@Kimundi Kimundi added A-closures Area: Closures (`|…| { … }`) A-borrow-checker Area: The borrow checker labels Jul 10, 2015
@seanmonstar
Copy link
Contributor

See also #24680

@shepmaster
Copy link
Member

shepmaster commented May 30, 2016

A similar example:

fn caller<F>(f: F)
    where F: Fn(&i32)
{
    f(&42);
}

fn main() {
    // Works
    caller(|a| println!("{}", a));

    // Doesn't work
    let f = |a| println!("{}", a);
    caller(f);
}

I think the problem is that in the non-working case, a isn't inferred to be a reference at all. The error message states (reworded a bit):

Actual:           std::ops::Fn<(_,)>
Expected: for<'r> std::ops::Fn<(&'r i32,)>

The error reporting stops at the "expected concrete lifetime, found bound lifetime parameter" aspect, but really the problem is that the closure argument isn't a reference. I'd expect to see Fn<(&_,)>.

If you force the closure to understand that the argument must be a reference, you get the same error but more sensible:

fn printer(a: &i32) { println!("{}", a) }
let f = |a| printer(a);
caller(f)
Actual:           std::ops::Fn<(&i32,)>
Expected: for<'r> std::ops::Fn<(&'r i32,)>

This appears to be discussed in #24680, as @seanmonstar mentioned.

@Mark-Simulacrum
Copy link
Member

Closing in favor of #41078.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-borrow-checker Area: The borrow checker A-closures Area: Closures (`|…| { … }`)
Projects
None yet
Development

No branches or pull requests

5 participants