发生这种情况是因为add
被定义为:
fn add<'a>(node: &'a mut Node, data: &'static str) -> &'a Node
这里指定了结果引用的生命周期应该等于传入引用的生命周期。这only可能的方式(不安全代码除外)是结果引用以某种方式从传入引用派生,例如,它引用传入引用指向的对象内的某个字段:
struct X {
a: u32,
b: u32,
}
fn borrow_a<'a>(x: &'a mut X) -> &'a mut u32 {
&mut x.a
}
然而,有no编译器知道的方式到底是什么通过仅查看函数签名来借用传入结构(通常,这是在编译使用该函数的代码时唯一可以做的事情)。因此,它无法知道以下代码在技术上是正确的:
let mut x = X { a: 1, b: 2 };
let a = borrow_a(&mut x);
let b = &mut x.b;
We我知道a
and b
是不相交的,因为它们指向结构的不同部分,但编译器无法知道这一点,因为其中没有任何内容borrow_a
的签名会暗示它(不可能有,Rust 不支持它)。
因此,编译器可以做的唯一明智的事情就是考虑整体 x
被借用直到引用返回borrow_a()
被丢弃。否则,可能会为同一数据创建两个可变引用,这违反了 Rust 别名保证。
请注意,以下代码是正确的:
let mut x = X { a: 1, b: 2 };
let a = &mut x.a;
let b = &mut x.b;
这里是编译器can看到那个a
and b
永远不要指向相同的数据,即使它们确实指向相同的结构内部。
对此没有解决方法,唯一的解决方案是重构代码,使其不具有此类借用模式。