【问题标题】:Can't borrow File from &mut self (error msg: cannot move out of borrowed content)无法从 &mut self 借用文件(错误消息:无法移出借用的内容)
【发布时间】:2015-03-18 01:11:42
【问题描述】:
use std::fs::File;
use std::io::Read;

pub struct Foo {
    maybe_file: Option<File>,
}

impl Foo {
    pub fn init(&mut self) {
        self.maybe_file = Some(File::open("/proc/uptime").unwrap());
    }

    pub fn print(&mut self) {
        let mut file = self.maybe_file.unwrap();
        let mut s = String::new();
        file.read_to_string(&mut s).unwrap();
        println!("Uptime: {}", s);
    }
}

fn main() {}

编译它会给我:

error[E0507]: cannot move out of borrowed content
  --> src/main.rs:14:24
   |
14 |         let mut file = self.maybe_file.unwrap();
   |                        ^^^^ cannot move out of borrowed content

为什么会这样?我该怎么做才能解决它?

【问题讨论】:

    标签: rust borrow-checker


    【解决方案1】:

    selfprint 中有&amp;mut Foo 类型,也就是说,它是对Foo 类型值的借用可变引用。默认情况下,Rust 中的类型移动所有权,也就是说,按值获取某些东西会使源静态无效并阻止程序员再次使用它(除非它被重新初始化)。在这种情况下,unwrap 具有签名:

    impl Option<T> {
        fn unwrap(self) -> T { ...
    

    也就是说,它按值获取Option 值,因此试图消耗它的所有权。因此,self.maybe_file.unwrap() 试图使用maybe_file 中的数据,这将使self 指向部分无效的数据(之后使用maybe_file 字段是非法的)。编译器无法使用借来的引用来强制执行此操作,这些引用必须始终有效,因为它们可以指向任何地方,因此移出是非法的。

    幸运的是,可以避免这个问题:as_ref 方法从 &amp;Option&lt;T&gt; 中创建一个 Option&lt;&amp;T&gt;as_mut 方法在 &amp;mut Option&lt;T&gt; 中创建一个 Option&lt;&amp;mut T&gt;。生成的Option 不再位于引用后面,因此通过unwrap 使用它是合法的:

    let mut file = self.maybe_file.as_mut().unwrap();
    

    这略有不同,因为 file 的类型为 &amp;mut File 而不是 File,但幸运的是 &amp;mut File 是其余代码所必需的。

    完成这项工作的另一种方法是使用手动模式匹配:

    match self.maybe_file {
        Some(ref mut file)  => println!(...),
        None => panic!("error: file was missing")
    }
    

    这与.as_mut().unwrap() 做的事情完全相同,只是更明确一点:ref mut 是创建一个直接指向self.maybe_file 占用的内存的引用,就像as_mut 一样。

    【讨论】:

    • 谢谢,这个答案对我帮助很大!
    猜你喜欢
    • 1970-01-01
    • 2017-10-15
    • 2018-04-04
    • 2015-03-27
    • 1970-01-01
    • 1970-01-01
    • 2015-04-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多