【问题标题】:What are the Rust borrowing rules regarding mutable internal references?关于可变内部引用的 Rust 借用规则是什么?
【发布时间】:2017-01-14 00:20:16
【问题描述】:

我不明白为什么会有这样的程序

#[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 也被借用为可变的

由于这两个程序基本上做同样的事情,从内存的角度来看,第二个程序似乎不会更不安全。我知道我必须缺少一些关于借用和范围规则的东西,但不知道是什么。

【问题讨论】:

    标签: rust


    【解决方案1】:

    为了使您的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 中的元组结构(或者如果现在甚至可以这样做),但如果是这样的话,那么两个版本实际上并没有太大区别会工作的。

    【讨论】:

    • 你可以在这里使用if let而不是match进行模式匹配,尽管我发现match更“面向未来”。
    • 为什么 match 更具未来性? “如果让”不是稳定的吗?
    • @avl_sweden 我的意思是随着项目的扩展,State 枚举有更多变体的可能性。
    【解决方案2】:

    match 语句中,您借用了self.state。借用作用域是词法的,所以它是在整个match 块中借用的。拨打self.print()时,需要借用self。但这是不可能的,因为self 的一部分已经被借用了。如果在match 语句之后移动self.print(),它将起作用。

    关于词法借用范围,您可以在Two bugs in the borrow checker every Rust developer should know about的第二部分阅读更多内容。相关问题:#6393#811

    【讨论】:

      猜你喜欢
      • 2022-11-30
      • 2021-11-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-02
      • 1970-01-01
      • 2015-04-15
      相关资源
      最近更新 更多