This is because the result of closure c
outlives the loop. For example, in the loop, you pass &s
to c
but at the end of the loop c
still exist. This is why the in-place construction of closure works. Even the following code works alright.
fn f1(v: &str) {}
fn main() {
for _ in 0..1 {
let s = String::new();
let c = |v| f1(v);
c(&s);
}
}
In essence, the borrowed reference cannot be held by someone when you know the reference cease to exist before the borrower.
Also note the following approaches work too;
fn f1(v: &str) {}
fn main() {
let c = f1;
for _ in 0..1 {
let s = String::new();
c(&s);
}
}
and
fn f1(v: &str) {}
fn c(v: &str) {}
fn main() {
for _ in 0..1 {
let s = String::new();
c(&s);
}
}
Because in both of these cases, your borrowed reference does not outlive the scopes. But in your closure syntax v
the input goes to f(v)
which is held by c
.
In a way you can think that c
is a variable that would hold onto the reference which dies before c
does.
Your example is interesting and might even be an edge case. In case you were wondering closures capture the surrounding unlike variables and functions. This is discussed here further rust book.
Because the following code compiles.
fn main() {
let mut c;
for _ in 0..1 {
let s = String::new();
c = &s ;
}
}
But this fails
fn main() {
let mut c;
for _ in 0..1 {
let s = String::new();
c = &s ;
}
println!("{c}");
}
Because compiler knows in previous scenario c
can be cleared right at the end of for loop, but the second one is a clear no, due to outlived reference.
I hope this shed some light on your question.