英文:
Why would rust error on accessing mutable borrow while immutable borrow isn't accessed anywhere?
问题
我无法理解为什么以下代码出错?
```rust
fn main() {
let mut v = vec![];
let z = &mut v;
let y = &v;
z.push(1);
println!("{:?}", z); // 访问可变借用
}
在上述情况中,我没有在任何地方访问 y,而且 Rust 应该能够编译它而没有任何问题。我可以在下面的代码中看到类似的行为。
fn main() {
let mut v = vec![];
let y = &v;
let z = &mut v;
z.push(1);
println!("{:?}", z); // 访问可变借用
}
在上述情况中,Rust 不会抱怨访问可变借用,因为没有在任何地方访问不可变借用。对于下面的情况,Rust 会抱怨,因为代码访问了不可变借用,这是完全可以理解的。
fn main() {
let mut v = vec![];
let y = &v;
let z = &mut v;
z.push(1);
println!("{:?}", y); // 访问不可变借用
}
<details>
<summary>英文:</summary>
I'm unable to understand why below code errors out ?
```rust
fn main() {
let mut v = vec![];
let z = &mut v;
let y = &v;
z.push(1);
println!("{:?}",z); //accessing mutable borrow
}
In the above scenario, I'm not accessing y anywhere and rust should be able to compile it without any problems. I can see similar behavior happening in below code.
fn main() {
let mut v = vec![];
let y = &v;
let z = &mut v;
z.push(1);
println!("{:?}",z); // accessing mutable borrow
}
In the above scenario, rust doesn't complain on accessing mutable borrow because immutable borrow isn't accessed anywhere. For below scenario rust complains as the code is accessing immutable borrow, which is completely understandable.
fn main() {
let mut v = vec![];
let y = &v;
let z = &mut v;
z.push(1);
println!("{:?}",y); // accessing immutable borrow
}
答案1
得分: 4
即使你不访问 y
,创建它就足以使任何现有的可变借用无效。
NLL(非词法生命周期) 改变的只是一个引用被认为存活直到其最后使用,而不是直到作用域的结束。但是引用总是被认为存活_一段时间_。
可以推测,你想要的行为没有被实现,因为它并不实用:一个从不被使用的引用几乎没有价值。
英文:
Even though you don't access y
, creating it is enough to invalidate any existing mutable borrows.
What NLL (non-lexical lifetimes) changed is only that a reference is considered alive until its last usage, and not until the end of the scope. But a reference is always considered alive for some time.
Presumably, the behavior you want was not implemented because it's not useful: there is little value in reference that is never used.
答案2
得分: 2
问题不在于您是否正在访问 y
,问题在于您在写 &v
时实际上是在访问 v
本身。请注意,如果您从 z
创建 y
,则您的代码将正常工作:
fn main() {
let mut v = vec![];
let z = &mut v;
let y = &*z;
z.push(1);
println!("{:?}", z); // 访问可变引用
}
请注意,这在原始代码的错误消息中有所体现:
error[E0502]: cannot borrow `v` as immutable because it is also borrowed as mutable
--> src/main.rs:4:13
|
3 | let z = &mut v;
| ------ mutable borrow occurs here
4 | let y = &v;
| ^^ immutable borrow occurs here
5 | z.push(1);
| --------- mutable borrow later used here
错误标记 &v
为问题所在,而不是 y
。
英文:
The problem isn't whether you're accessing y
, the problem is that you're accessing v
itself when you write &v
. Note that your code works if you create y
from z
:
fn main() {
let mut v = vec![];
let z = &mut v;
let y = &*z;
z.push(1);
println!("{:?}",z); //accessing mutable borrow
}
Note that this is evidenced in the error message for your original code:
error[E0502]: cannot borrow `v` as immutable because it is also borrowed as mutable
--> src/main.rs:4:13
|
3 | let z = &mut v;
| ------ mutable borrow occurs here
4 | let y = &v;
| ^^ immutable borrow occurs here
5 | z.push(1);
| --------- mutable borrow later used here
The error marks &v
as problematic, not y
.
答案3
得分: 1
2 条规则:
1- 不可变和可变引用不能同时存在于同一个变量上
2- 不可变引用的生命周期持续到最后一次使用
第一个代码失败,因为不可变和可变应该不应该同时存在(然而它们却同时存在,违反了Rust的借用规则)。变量 z 是可变的,它的作用域从第 3 行(let z = &mut v;
)开始,持续到第 6 行(println!("{:?}",z)
)。在这段时间内,不应该存在不可变引用。但是在这个作用域内确实存在不可变引用,它在第 4 行,即let y = &v;
。
在第二个编译通过的代码中,不可变和可变不存在同时存在的情况。变量 y 是一个引用,其作用域从第 3 行开始并在该行结束(因为我们之后不再使用变量 y)。变量的作用域从第一次使用它的行开始,到最后一次使用它的行结束。
在第一个代码中,y 和 z 同时存在,而在第二个代码中,它们没有同时存在。
英文:
2 rules:
1- Immutable and mutable reference to the same variable cannot exist at the same time
2- The lifetime of an immutable reference lasts till its last usage
The first code fails because the immutable and mutable should not CO-EXIST (however they co-exist which is against rust borrowing rules). The variable z is mutable and its scope is from line 3 (let z = &mut v;
) till line 6 (println!("{:?}",z)
). During this duration, the immutable reference should not exist. However the immutable reference exists during this scope which is on line 4 which is
let y = &v;
.
fn main() {
let mut v = vec![];
let z = &mut v; // --------------------------------- its lifetime starts here
let y = &v; // y's lifetime start and ends here |
z.push(1); // | z lifetime ends here
println!("{:?}",z);
}
// as you see y and z coexists
In the second code which compiles, is due to the fact that immutable and mutable does not co-exist. The variable y is a reference with a scope which starts and ends at the line 3 (since we are not using variable y afterwards). The scope of a variable starts from the line on which it is first used and ends on the line on which it is last used.
fn main() {
let mut v = vec![];
let y = &v; // y's lifetime starts and ends here
let z = &mut v; // z's lifetime starts here
z.push(1);
println!("{:?}",z); // accessing immutable borrow
}
// as you see y and z does not coexist
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论