以下代码无法编译:
fn foo<'a, F: Fn() -> &'a str>(vec: Vec<i32>, fun: F) -> impl Iterator<Item = i32> {
println!("{}", fun());
vec.into_iter()
}
fn main() {
let s = "hello, world!".to_string();
let iter = foo(vec![1, 2, 3], || &s);
drop(s);
for x in iter {
println!("{}", x);
}
}
error[E0505]: cannot move out of `s` because it is borrowed
--> src/main.rs:9:10
|
8 | let iter = foo(vec![1, 2, 3], || &s);
| -- - borrow occurs due to use in closure
| |
| borrow of `s` occurs here
9 | drop(s);
| ^ move out of `s` occurs here
10 |
11 | for x in iter {
| ---- borrow later used here
如果我将foo
的声明替换为以下内容,它将被编译。
fn foo<'a, F: Fn() -> &'a str>(vec: Vec<i32>, fun: F) -> <Vec<i32> as IntoIterator>::IntoIter {
// ...
}
这让我相信impl Trait
类型的借用检查更加保守:即使实际上没有捕获fun
,编译器也会假设返回的对象捕获了它。
然而,这个有趣的例子可以通过编译:
fn foo(s: &str) -> impl Iterator<Item = i32> {
println!("{}", s);
vec![1, 2, 3].into_iter()
}
fn main() {
let s = "hello, world!".to_string();
let iter = foo(&s);
drop(s);
for x in iter {
println!("{}", x);
}
}
在这里,编译器似乎并不认为返回的 impl Iterator<Item = i32>
借用了 s
。
返回的impl Trait
类型是如何进行借用检查的?什么情况下假定它们借用其他函数参数(比如第一个示例)?什么情况下假定它们不借用其他参数(比如后面的示例)?
-> impl 'static + Iterator<Item=i32>
在这里会有所作为,但实际上并没有。 - eggyal