【问题标题】:Cannot move out of borrowed content from closure return value无法从关闭返回值中移出借来的内容
【发布时间】:2019-10-18 01:56:37
【问题描述】:

我在处理中型项目时发现了这个问题。以下 sn-p 是对该问题的一个最小总结。

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

为了保持关闭状态,我在 Box 中使用了 FnMut 特征。我还将它包裹在 Option 中,这样我就可以在实例创建后设置闭包。

我从这里提出的问题中得到了一点基础:structs with boxed vs. unboxed closures

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吗?结果HashSet?或者可能是集合内的值? 我做错了什么?

【问题讨论】:

    标签: rust closures borrow-checker


    【解决方案1】:

    您遇到的麻烦是在Option 上调用unwrap 会消耗它——它需要self 作为参数。在run() 内部,您的MyType 仅对自身有一个&amp;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!");
                }
            }
        }
    

    【讨论】:

    猜你喜欢
    • 2019-08-29
    • 2018-04-04
    • 1970-01-01
    • 1970-01-01
    • 2016-09-15
    • 2015-03-25
    • 1970-01-01
    • 1970-01-01
    • 2017-10-15
    相关资源
    最近更新 更多