似乎阴影变量不会释放它所持有的借用参考。以下代码无法编译:
fn main() {
let mut a = 40;
let r1 = &mut a;
let r1 = "shadowed";
let r2 = &mut a;
}
显示错误消息:
error[E0499]: cannot borrow `a` as mutable more than once at a time
--> src/main.rs:5:19
|
3 | let r1 = &mut a;
| - first mutable borrow occurs here
4 | let r1 = "shadowed";
5 | let r2 = &mut a;
| ^ second mutable borrow occurs here
6 | }
| - first borrow ends here
我希望代码能够编译,因为在借用第二个引用r1
之前,第一个引用r2
被遮蔽了。显然,第一次借用直到阻止结束,尽管在第4行之后不再可以进入。为什么会这样?
答案 0 :(得分:5)
TL; DR:阴影是关于名字查找,借用是关于生命周期。
从编译器的角度来看,变量没有名称:
fn main() {
let mut __0 = 40;
let __1 = &mut __0;
let __2 = "shadowed";
let __3 = &mut __0;
}
这对于人类来说不是非常易读,因此该语言允许我们使用描述性名称。
阴影是重用名称的一个限制,对于“阴影”变量的词法范围,它将名称解析为“阴影”(__2
此处)而不是“原始”一个(__1
这里)。
然而,仅仅因为无法再访问旧版本并不意味着它不再生活: Shadowing!= Assignment 。这在不同的范围内尤其值得注意:
fn main() {
let i = 3;
for i in 0..10 {
}
println!("{}", i);
}
将始终打印3
:一旦阴影变量的范围结束,名称将再次解析为原始版本!
答案 1 :(得分:2)
它不像原来的r1
在被遮蔽后不再存在;考虑为您的代码生成的MIR没有最后一行(r2
绑定):
fn main() -> () {
let mut _0: (); // return pointer
scope 1 {
let mut _1: i32; // "a" in scope 1 at src/main.rs:2:9: 2:14
scope 2 {
let _2: &mut i32; // "r1" in scope 2 at src/main.rs:3:9: 3:11
scope 3 {
let _3: &str; // "r1" in scope 3 at src/main.rs:4:9: 4:11
}
}
}
bb0: {
StorageLive(_1); // scope 0 at src/main.rs:2:9: 2:14
_1 = const 40i32; // scope 0 at src/main.rs:2:17: 2:19
StorageLive(_2); // scope 1 at src/main.rs:3:9: 3:11
_2 = &mut _1; // scope 1 at src/main.rs:3:14: 3:20
StorageLive(_3); // scope 2 at src/main.rs:4:9: 4:11
_3 = const "shadowed"; // scope 2 at src/main.rs:4:14: 4:24
_0 = (); // scope 3 at src/main.rs:1:11: 5:2
StorageDead(_3); // scope 2 at src/main.rs:5:2: 5:2
StorageDead(_2); // scope 1 at src/main.rs:5:2: 5:2
StorageDead(_1); // scope 0 at src/main.rs:5:2: 5:2
return; // scope 0 at src/main.rs:5:2: 5:2
}
}
请注意,当"shadowed"
绑定(_3
)时,它不会更改与原始r1
绑定相关的任何内容(_2
);名称r1
不再适用于可变引用,但原始变量仍然存在。
我不认为你的例子是一个非常有用的阴影案例;它的通常应用,例如循环体,更有可能利用它。