对我来说,为什么像
这样的程序并不直观#[derive(Debug)]
struct Test {
buf: [u8; 16],
}
impl Test {
fn new() -> Test {
Test {
buf: [0u8; 16],
}
}
fn hi(&mut self) {
self.buf[0] = 'H' as u8;
self.buf[1] = 'i' as u8;
self.buf[2] = '!' as u8;
self.print();
}
fn print(&self) {
println!("{:?}", self);
}
}
fn main() {
Test::new().hi();
}
编译并运行没有任何问题,但是像
这样的程序#[derive(Debug)]
enum State {
Testing([u8; 16]),
}
#[derive(Debug)]
struct Test {
state: State,
}
impl Test {
fn new() -> Test {
Test {
state: State::Testing([0u8; 16]),
}
}
fn hi(&mut self) {
match self.state {
State::Testing(ref mut buf) => {
buf[0] = 'H' as u8;
buf[1] = 'i' as u8;
buf[2] = '!' as u8;
self.print();
},
}
}
fn print(&self) {
println!("{:?}", self);
}
}
fn main() {
Test::new().hi();
}
编译时出现错误
错误[E0502]:无法将
*self
借用为不可变因为self.state.0
也被借用为可变
由于两个程序基本上都是相同的东西,第二个似乎从内存的角度看起来不太安全。我知道必须有一些关于我必须缺少的借用和范围规则,但不知道是什么。
答案 0 :(得分:3)
为了使hi
函数正常工作,您只需将print
移出其match
表达式中引入的可变扩展的范围:
fn hi(&mut self) {
match self.state {
State::Testing(ref mut buf) => {
buf[0] = 'H' as u8;
buf[1] = 'i' as u8;
buf[2] = '!' as u8;
},
}
self.print();
}
由于第二种情况中存在match
块,您的两个变体不相等。我不知道如何在没有模式匹配的情况下直接访问enum
中的元组结构(或者如果现在甚至可能这样),但如果是这样的话,那么实际上并不多差异和两个版本都可以。
答案 1 :(得分:2)
在match
声明中,您借用self.state
。借用范围是词法,因此它在整个match
块中借用。致电self.print()
时,您需要借用self
。但这是不可能的,因为self
的一部分已经被借用了。如果您在self.print()
语句后移动match
,则会有效。
关于词汇借阅范围,您可以在Two bugs in the borrow checker every Rust developer should know about的第二部分阅读更多内容。相关问题:#6393,#811。