use std::fs::File;
use std::io::prelude::*;
use std::io::BufReader;
fn main() {
let f = File::open("test.txt").expect("Can't open");
let mut b = BufReader::new(f);
let v = b.fill_buf().unwrap();
println!("v: {:?}", v);
b.consume(v.len());
}
Run Code Online (Sandbox Code Playgroud)
无法编译,错误是
error[E0499]: cannot borrow `b` as mutable more than once at a time
--> src/main.rs:10:5
|
7 | let v = b.fill_buf().unwrap();
| ------------ first mutable borrow occurs here
...
10 | b.consume(v.len());
| ^^^^^^^^^^-------^
| | |
| | first borrow later used here
| second mutable borrow occurs here
Run Code Online (Sandbox Code Playgroud)
将最后一行更改为:
let len = v.len();
b.consume(len);
Run Code Online (Sandbox Code Playgroud)
一切都很好。
我无法理解为什么第一个示例借用了两次东西,以及为什么将长度存储在变量中并将该变量传递给b.consume()可以 - 有人可以解释为什么 2. 变体可以,而第一个则不行?
当您遇到此类问题时,稍微简化一下事情会有所帮助。您可能知道,方法语法是关联函数调用的语法糖:
b.consume(v.len());
// desugars to
BufRead::consume(&mut b, [_]::len(v));
Run Code Online (Sandbox Code Playgroud)
参数表达式通常是从左到右计算的,因此我们在b释放 中持有的引用之前尝试获取一个新的可变引用v。在某些情况下,编译器可以识别并自动避免此问题,但这似乎不是其中之一。
你可能会问“为什么它说第二个可变引用?v是一个不可变引用!” 那么,当您调用 时, in 引用的生命周期v与可变引用的生命周期相关联b.fill_buf()。因此编译器认为可变引用b必须保持有效直到v被释放。
该修复有效的原因是它翻转了参数的顺序,v.len()首先评估,然后释放第一个引用。