4

Code:

fn main() {
    let f = |str: &str| str.trim();
    println!("{}", f("  foo bar  "));
}

Error:

error: lifetime may not live long enough
 --> src/main.rs:2:25
  |
2 |     let f = |str: &str| str.trim();
  |                   -   - ^^^^^^^^^^ returning this value requires that `'1` must outlive `'2`
  |                   |   |
  |                   |   return type of closure is &'2 str
  |                   let's call the lifetime of this reference `'1`

Playground

The same closure works if used as an argument to a function, e.g. vec.iter().map(|str| str.trim()).

Is it possible for a standalone closure, like in my code, to take &str and return &str with the same lifetime?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Dogbert
  • 212,659
  • 41
  • 396
  • 397
  • TL;DR: no. [The duplicate applied to your situation](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=5c72c8152f84a33509f3376fe0369305). – Shepmaster Mar 29 '21 at 13:35
  • 2
    Also, pay attention to [Shepmaster's answer](https://stackoverflow.com/a/46198877/1600898) to the original question, which is much more useful than the accepted answer. – user4815162342 Mar 29 '21 at 13:42
  • Thanks @user4815162342 and Shepmaster, I understand now. – Dogbert Mar 31 '21 at 10:45

1 Answers1

1

Not sure why the inference fails, but for some reason the borrow checker treats annotations on the closure differently from annotations on fn.

This works:

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=cfcfb4877894d3ed7fbce88bfeddb45c

fn main() {
    let f: fn(&str) -> &str = |s| s.trim();
    println!("{}", f("  foo bar  "));
}
sebpuetz
  • 2,430
  • 1
  • 7
  • 15
  • `fn(&str) -> &str` causes the closure to be coerced to a function pointer, which (in this trivial case is likely the same, but) may inhibit inlining and/or require an indirection. Moreover, the closure can't capture anything, so you may as well just write `fn f(s: &str) -> &str { s.trim() }`. Shepmaster's answer to the linked question doesn't have either of these drawbacks. – trent Mar 29 '21 at 13:47
  • This is a nice hack, I didn't know you could assign a closure to a variable of type `fn(...) -> ...`. But I suspect it won't help the OP's actual use case which likely requires a capturing closure which won't be `fn()`. – user4815162342 Mar 29 '21 at 13:48