考虑以下Rust代码:
fn foo<'a, T, F, G>(x: &'a mut T, f: F, g: G)
where
T: 'a,
F: Fn(&'a T) -> &'a T,
G: Fn(&'a mut T) -> &'a mut T,
{
{
f(x);
}
g(x);
}
fn main() {
let mut x = 5;
foo(&mut x, |a| a, |a| a);
}
这会导致编译器错误:
error[E0502]: cannot borrow `*x` as mutable because it is also borrowed as immutable
--> src/main.rs:10:7
|
8 | f(x);
| - immutable borrow occurs here
9 | }
10 | g(x);
| ^ mutable borrow occurs here
11 | }
| - immutable borrow ends here
我不明白为什么x
的不可变借项在第11行结束。例如,f(x)
在第9行的内部范围内。但是,{{1 }}没有绑定任何变量,因此我认为借用应该在第8行结束,甚至不需要内部作用域。
答案 0 :(得分:4)
让我们考虑一下this example:
fd_set
这是完全合法的,因为可以保证函数select()
采用与fn foo<'a, T, F, G>(x: &'a mut T, mut f: F, g: G)
where
T: 'a,
F: FnMut(&'a T) -> &'a T,
G: Fn(&'a mut T) -> &'a mut T,
{
{
f(x);
}
}
fn main() {
let mut x = 5;
let mut y = std::cell::RefCell::new(&0);
foo(&mut x, |a| { y.replace(&a); a }, |a| a);
}
相同的生存期的引用,因此它可以存储对{{1}的引用}。但是您不能用f
来调用x
,因为x
可能已经存储了g
。
如果您将x
更改为:
f
(由于生命周期删除规则)等效于:
x
然后foo
isn't allowed to store the reference x
:
fn foo<T, F, G>(x: &mut T, mut f: F, g: G)
where
F: FnMut(&T) -> &T,
G: Fn(&T) -> &T,
但将fn foo<'a, T, F, G>(x: &'a mut T, mut f: F, g: G)
where
T: 'a,
F: for<'b> FnMut(&'b T) -> &'b T,
G: for<'c> Fn(&'c T) -> &'c T,
称为f
becomes legal。