Description
(Spawned off of #55526.)
Consider the following code (play):
fn foo(input: &str) -> &str {
let id = |x: &str| -> &str { x };
id(input)
}
The above does not compile today.
Error diagnostic:
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> src/main.rs:2:27
|
2 | let id = |x: &str| -> &str { x };
| ^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the body at 2:14...
--> src/main.rs:2:14
|
2 | let id = |x: &str| -> &str { x };
| ^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:2:34
|
2 | let id = |x: &str| -> &str { x };
| ^
note: but, the lifetime must be valid for the anonymous lifetime #1 defined on the function body at 1:1...
--> src/main.rs:1:1
|
1 | / fn foo(input: &str) -> &str {
2 | | let id = |x: &str| -> &str { x };
3 | | id(input)
4 | | }
| |_^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:3:5
|
3 | id(input)
| ^^^^^^^^^
However, discussions with @nikomatsakis lead us to wonder why lifetime elision is not being applied to the type annotation attached to the closure. Since there is a single input argument type and a single return type, it seems reasonable to apply lifetime elision, yielding the type for <'r> (&'r str) -> &'r str
.
I believe fixing this is actually pretty trivial, based on some initial experimentation with the code here:
rust/src/librustc/middle/resolve_lifetime.rs
Lines 2112 to 2117 in 21cb46a
(The question will only be whether there are unintended consequences of the fix; I'm still looking into that.)
(This might require an RFC, not sure yet.)