为什么只有在声明在循环外时才会发生这种不变性错误? [英] Why does this immutability error only happens if declaration is outside the loop?
问题描述
我试图用我从文件中获取的一些数据填充缓冲区,然后从该缓冲区读取以处理该数据.所有这一切都在循环中反复进行.
I am trying to fill a buffer with some data I get from a file, and then read from that buffer to do stuff with that data. All of that iteratively, inside a loop.
如果我这样做,它会完美编译:
If I do this, it compiles perfectly:
use std::fs::File;
use std::io::{BufReader, IoSliceMut, Read};
fn do_something(buffer_0: &[u8; 8], buffer_1: &[u8; 2]) {
// Do something
}
fn main() {
let file = File::open("/path/to/file").expect("Error opening file");
let mut reader = BufReader::new(file);
let buffer_0 = &mut [0; 8];
let buffer_1 = &mut [0; 2];
loop {
let buffer = &mut [IoSliceMut::new(buffer_0), IoSliceMut::new(buffer_1)];
reader
.read_vectored(buffer)
.expect("Error reading from file");
do_something(buffer_0, buffer_1);
}
}
现在,如果我在循环之外声明 buffer
,就像这样:
Now, if I declare buffer
outside of the loop, like this:
use std::fs::File;
use std::io::{BufReader, IoSliceMut, Read};
fn do_something(buffer_0: &[u8; 8], buffer_1: &[u8; 2]) {
// Do something
}
fn main() {
let file = File::open("/path/to/file").expect("Error opening file");
let mut reader = BufReader::new(file);
let buffer_0 = &mut [0; 8];
let buffer_1 = &mut [0; 2];
let buffer = &mut [IoSliceMut::new(buffer_0), IoSliceMut::new(buffer_1)];
loop {
reader
.read_vectored(buffer)
.expect("Error reading from file");
do_something(buffer_0, buffer_1);
}
}
出现如下编译错误:
error[E0502]: cannot borrow `*buffer_0` as immutable because it is also borrowed as mutable
--> src/main.rs:21:22
|
15 | let buffer = &mut [IoSliceMut::new(buffer_0), IoSliceMut::new(buffer_1)];
| -------- mutable borrow occurs here
...
19 | .read_vectored(buffer)
| ------ mutable borrow later used here
20 | .expect("Error reading from file");
21 | do_something(buffer_0, buffer_1);
| ^^^^^^^^ immutable borrow occurs here
buffer_1
当然也一样.
我不明白为什么这段代码在循环中被认为是不安全的.另外,是否可以在不移动 buffer
声明的情况下使其安全?
I don't understand why this code is considered unsafe inside the loop. Also, is it possible to make it safe without moving the buffer
declaration?
非常感谢 Rust 大师的智慧 :)
Rust gurus wisdom is much appreciated :)
推荐答案
在第一个示例中,buffer
的每个实例仅持续循环的一次迭代.由于非词法生命周期,编译器可以计算出您在调用 read_vectored
后不会重用 IoSliceMut
的那些实例,因此它们持有的可变借用是发布,代码编译.
In the first example, each instance of buffer
lasts only for one iteration of the loop. Due to non-lexical lifetimes, the compiler can work out that you don't reuse those instances of IoSliceMut
after your call to read_vectored
, so the mutable borrows that they hold are released, and the code compiles.
在您的第二个示例中,您明确表示应该为整个循环保留 IoSliceMut
的这两个实例,并且它们应该用于每次调用read_vectored
- 因此他们的可变借用不可能在最后一次迭代之前被释放.
In your second example, you're explicitly saying that those two instances of IoSliceMut
should be kept for the entire loop, and they should be used for every call to read_vectored
- therefore their mutable borrows cannot not possibly be released until the very last iteration.
这篇关于为什么只有在声明在循环外时才会发生这种不变性错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!