本文介绍了无法从 &mut self 借用文件(错误消息:无法移出借用的内容)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

Why is this happening? What do I do to solve it?

推荐答案

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

self has type &mut Foo in print, that is, it is a borrowed mutable reference to a value of type Foo. Types in Rust move ownership by default, that is, taking something by-value will statically invalidate the source and stop the programmer from using it again (unless it is reinitialized). In this case, unwrap has the signature:

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

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

That is, it is taking the Option value by-value and thus trying to consume ownership of it. Hence, self.maybe_file.unwrap() is trying to consume the data in maybe_file which would leave self pointing to partially invalid data (it is illegal to use the maybe_file field after that). There's no way the compiler can enforce this with borrowed references which have to be valid always as they could point anywhere, so it is illegal to move out.

幸运的是,可以避免这个问题:as_ref 方法从 &Optionas_mut 方法创建一个 &mut Option 中的 Option.结果 Option 不再位于引用之后,因此通过 unwrap 使用它是合法的:

Fortunately, one can avoid this problem: the as_ref method creates an Option<&T> out of an &Option<T> and the as_mut method creates an Option<&mut T> out of an &mut Option<T>. The resulting Option is then no longer behind a reference and so it is legal to consume it via unwrap:

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

这略有不同,因为 file 的类型为 &mut File 而不是 File,但幸运的是 &mut File 是其余代码所需的全部内容.

This differs slightly because file has type &mut File instead of File, but fortunately &mut File is all that is necessary for the rest of the code.

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

Another approach to making this work is using manual pattern matching:

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一样.

This is doing exactly the same thing as the .as_mut().unwrap() just more explicitly: the ref mut is create a reference pointing directly into the memory occupied by self.maybe_file, just like as_mut.

这篇关于无法从 &amp;mut self 借用文件(错误消息:无法移出借用的内容)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-23 06:20