简体   繁体   English

什么是关于可变内部引用的Rust借用规则?

[英]What are the Rust borrowing rules regarding mutable internal references?

It's not intuitive to me why a program like 对我来说,为什么一个类似的程序并不直观

#[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();
}

compiles and runs without any problem, but a program like 编译和运行没有任何问题,但像一个程序

#[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();
}

errors during compilation with an error of 编译过程中的错误,错误

error[E0502]: cannot borrow *self as immutable because self.state.0 is also borrowed as mutable 错误[E0502]:不能将*self借用为不可变因为self.state.0也被借用为可变的

Since both programs do essentially the same thing, the second doesn't seem like it would be somehow more unsafe from a memory perspective. 由于两个程序基本上都是相同的东西,第二个似乎不会从内存的角度看起来更不安全。 I know there must be something about the borrowing and scoping rules that I must be missing, but have no idea what. 我知道必须要有一些关于我必须缺少的借用和范围规则,但不知道是什么。

In order to make your hi function work you just need to move print out of the scope of the mutable borrow introduced in its match expression: 为了使你的hi函数工作,你只需要将printmatch表达式中引入的可变扩展的范围:

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();
}

Your two variants are not equivalent due to the presence of the match block in the second case. 由于第二种情况中存在match块,您的两个变体不相等。 I don't know how to directly access the tuple struct in the enum without pattern matching (or if this is even possible right now), but if it was the case, then there would in fact be not much difference and both versions would work. 我不知道如何在没有模式匹配的情况下直接访问enum的元组结构(或者如果现在甚至可能这样),但如果是这样的话,那么实际上没有太大区别,两个版本都可以工作。

In the match statement, you borrow self.state . match语句中,您借用self.state Borrow scopes are lexical, so it is borrowed in the entire match block. 借用范围是词汇,因此它在整个match块中借用。 When you call self.print() , you need to borrow self . 当你调用self.print() ,你需要借用self But that is not possible, because part of self is already borrowed. 但这是不可能的,因为self一部分已经被借用了。 If you move self.print() after the match statement, it will work. 如果在match语句之后移动self.print() ,它将起作用。

Regarding the lexical borrow scope, you can read more in the second part of Two bugs in the borrow checker every Rust developer should know about . 关于词汇借用范围,您可以在每个Rust开发人员应该了解的借用检查器中两个错误的第二部分中阅读更多内容 Related issues: #6393 , #811 . 相关问题: #6393#811

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM