Content pfp
Content
@
0 reply
0 recast
0 reaction

Agost Biro pfp
Agost Biro
@agostbiro
Let’s try a more difficult one with closures. What’s wrong with this closure let closure = |x: &str| x;
6 replies
0 recast
4 reactions

franco pfp
franco
@francos.eth
You would need to specify a lifetime since you’re returning a borrowed reference. I don’t remember right now if you can annotate lifetimes in closures 😅 but you could do: let closure = |x: &str| x.to_owned();
2 replies
0 recast
1 reaction

Agost Biro pfp
Agost Biro
@agostbiro
Very warm! Why does this work though? fn foo(s: &str) -> &str { s }
2 replies
0 recast
1 reaction

franco pfp
franco
@francos.eth
Lifetime elision rules. The param s gets a lifetime because its a ref, since there is only one input lifetime it gets assigned to the output. I don’t get why the same doesn’t apply to the closure though. Maybe depends on the context of the closure and how its used 🤔
1 reply
0 recast
1 reaction

Agost Biro pfp
Agost Biro
@agostbiro
Yes! This is a wart on closures: lifetime elision works different than for functions for historical reasons and it’s impossible to change it without breaking backwards compatibility. One possible fix is static ref with trait: let c: &dyn Fn(&str) -> &str = &|x: &str| x;
1 reply
0 recast
1 reaction

Agost Biro pfp
Agost Biro
@agostbiro
More info: https://github.com/pretzelhammer/rust-blog/blob/master/posts/common-rust-lifetime-misconceptions.md#10-closures-follow-the-same-lifetime-elision-rules-as-functions
1 reply
0 recast
1 reaction

franco pfp
franco
@francos.eth
🥲 interesting! Is this something you encounter often? I think i never had before
1 reply
0 recast
1 reaction

Agost Biro pfp
Agost Biro
@agostbiro
No, it's not a common problem, bc closure arg types are usually inferred and then elision works, but it can be very confusing when reorganizing some code and it suddenly stops working. E.g. turning this Some(&0_u64).map(|x| x) into let c = |x: &u64| x; Some(&0_u64).map(c) doesn't work 😅
0 reply
0 recast
0 reaction