fn main() {
let word = String::from("hello");
let predicate = |p| p == &word;
predicate(&String::from("hello")); // error E0716, temporary value dropped ...
predicate(&String::from("hello"));
}
i can not understand.in my understanding,although &String::from("hello") is a temporary value, "==" expression return a bool value, rather than a dangling pointer, why error E0716 showed in this case?
but when i delete the last closure call like this:
fn main() {
let word = String::from("hello");
let predicate = |p| p == &word;
predicate(&String::from("hello"));
}
it can build successfully. why the error don't show again?
or add type annotation for closure arg like this:
fn main() {
let word = String::from("hello");
let predicate = |p: &String| p == &word;
predicate(&String::from("hello"));
predicate(&String::from("hello"));
}
it also can build successfully.
I've been confused for a while about this,i want to know the reason. please help me.
without type annotation, the parameter type of the closure is inferred to have the same type of the captured context &word. so, the synthesized closure type looks roughly like this:
the borrow checker can solve the lifetime if you only call it once, since there's a single lifetime. however, if you call it twice with different temporary lifetimes, if fails to unify them because these two lifetimes don't overlap with each other.
with a explicit parameter type annotation, the synthesized Fn looks like this:
In general the compiler is bad at inferring when a closure parameter should accept any lifetime, and very bad at inferring when it should accept any lifetime and return the input lifetime too.
An annotation with an elided lifetime, like |p: &String|, solves the first problem, but notoriously not the second problem. For those you can often use a "funnel" workaround:
// The identity function, but with a trait bound that influences the
// compiler's closure inference when the closure is directly passed
// to this function.
fn funnel<F: Fn(&String) -> Option<&str>>(f: F) -> F { f }
The reason why the closure inference bad? Probably a combination of "it's hard to infer the correct thing" and "it's a breaking change to alter how it works now". This might be the most pertinent issue about it.
Those challenges are almost always present with purely inference-based approaches, so IMO the actual solution is some way for the programmer to annotate what they want. There's an RFC that gets us part way there, but it's not stable. (And I'd still want something more complete if it was.)