简体   繁体   中英

Why does this closure's lifetime change based on seemingly unrelated types?

With the code

fn foo<'a, 'b>(
    state: &'b mut i32,
) -> impl FnMut(&'a str) -> &'static str + 'b {
    |s| "hi"
}

I get an error

error[E0482]: lifetime of return value does not outlive the function call
112 | ) -> impl FnMut(&'a str) -> &'static str + 'b {
    |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: the return value is only valid for the lifetime `'a` as defined on the function body at 110:9
110 | fn foo1<'a, 'b>(
    |         ^^

But somehow the code

fn foo2<'a, 'b>(
    state: &'b mut Option<&'a i32>,
) -> impl FnMut(&'a str) -> &'static str + 'b {
    |s| "hi"
}

compiles without errors. Why does the type of state change the lifetime of the closure?

With type &'b mut Option<&'a i32> , Rust infers the lifetime bound 'a: 'b ( 'a outlives 'b ). This bound is required for the function signature to be well-formed. You can add this bound explicitly to avoid the error:

fn foo<'a, 'b>(
    state: &'b mut i32,
) -> impl FnMut(&'a str) -> &'static str + 'b
where
    'a: 'b,
{
    |s| "hi"
}

However, if no parameter uses 'a , then 'a should be a higher-rank trait bound instead:

fn foo<'b>(
    state: &'b mut i32,
) -> impl for<'a> FnMut(&'a str) -> &'static str + 'b {
    |s| "hi"
}

The Fn family of traits are special in that they allow you to omit the lifetime entirely (following the same elision rules as fn signatures), so this is equivalent:

fn foo<'b>(
    state: &'b mut i32,
) -> impl FnMut(&str) -> &'static str + 'b {
    |s| "hi"
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM