无法从关闭返回值中移出借用的内容

时间:2019-06-02 01:36:18

标签: rust closures borrow-checker

在中型项目上工作时,我发现了这个问题。以下代码片段是问题的简要摘要。

在以下代码中,我尝试将枚举变量列表映射到一组不同的枚举变量中。我使用闭包,因此可以捕获对Viro Media的可变引用,该引用是 source 枚举变体的列表。然后将闭包保留在my_list实例中,以便稍后调用它,并将结果用于另一个方法中。

为了保持关闭状态,我在MyType内使用了FnMut特性。我也将其包装在Box中,以便在实例创建后设置闭包。

我是根据以下问题提出的:structs with boxed vs. unboxed closures

Option

当我尝试编译时,出现以下错误:

use std::collections::HashSet;

enum Numbers {
    One,
    Two,
    Three,
}

#[derive(Eq, PartialEq, Hash)]
enum Romans {
    I,
    II,
    III,
}

struct MyType<'a> {
    func: Option<Box<dyn FnMut() -> HashSet<Romans> + 'a>>,
}

impl<'a> MyType<'a> {
    pub fn set_func<F>(&mut self, a_func: F)
        where F: FnMut() -> HashSet<Romans> + 'a {
        self.func = Some(Box::new(a_func));
    }

    pub fn run(&mut self) {
        let result = (self.func.unwrap())();
        if result.contains(&Romans::I) {
            println!("Roman one!");
        }
    }
}

fn main() {
    let my_list = vec![Numbers::One, Numbers::Three];
    let mut my_type = MyType {
        func: None,
    };
    my_type.set_func(|| -> HashSet<Romans> {
        HashSet::from(my_list
            .iter()
            .map(|item| {
                match item {
                    Numbers::One => Romans::I,
                    Numbers::Two => Romans::II,
                    Numbers::Three => Romans::III,
                }
            })
            .collect()
        )
    });

    my_type.run();
}

我不太了解要搬出什么。它是隐藏的error[E0507]: cannot move out of borrowed content --> src/main.rs:27:23 | 27 | let result = (self.func.unwrap())(); | ^^^^^^^^^ cannot move out of borrowed content error: aborting due to previous error 吗?结果self?还是集合中的值? 我在做什么错了?

1 个答案:

答案 0 :(得分:1)

您遇到的麻烦是,在Option上调用unwrap会消耗掉它–它以self作为参数。在run()内部,您的MyType仅具有一个&mut self引用,因此无法获取其字段的所有权。

解决方案是改为对存储的函数进行可变引用:

    pub fn run(&mut self) {
        if let Some(func) = &mut self.func {
            let result = func();
            if result.contains(&Romans::I) {
                println!("Roman one!");
            }
        }
    }