rub*_*ubo 7 rust borrow-checker
以下代码无法编译:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
如果我将foo
的签名替换为
fn foo<'a, F: Fn() -> &'a str>(vec: Vec<i32>, fun: F) -> <Vec<i32> as IntoIterator>::IntoIter {
// ...
}
Run Code Online (Sandbox Code Playgroud)
这让我相信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);
}
}
Run Code Online (Sandbox Code Playgroud)
这里编译器似乎没有假设返回的impl Iterator<Item = i32>
借用s
.
返回impl Trait
类型究竟是如何借用检查的?他们什么时候假设借用其他函数参数,就像在第一种情况下一样?什么时候假设他们不这样做,就像在后一种情况下一样?