Невозможно выйти из заимствованного содержимого из возвращаемого значения - PullRequest
0 голосов
/ 02 июня 2019

Я обнаружил эту проблему при работе над проектом среднего размера.Следующий фрагмент представляет собой минимальную сводку проблемы.

В следующем коде я пытаюсь отобразить список вариантов перечисления в набор различных вариантов перечисления.Я использую замыкание, чтобы получить изменяемую ссылку на my_list, представляющую собой список вариантов перечисления source .Затем замыкание сохраняется внутри экземпляра MyType, чтобы его можно было вызвать позже, а результат использовать в другом методе.

Чтобы сохранить замыкание, я использовал черту FnMut внутри Box.Я также обернул это внутри 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?В результате HashSet?или, может быть, значения внутри набора?Что я делаю не так?

1 Ответ

1 голос
/ 02 июня 2019

Проблема в том, что при вызове unwrap на Option это потребляется - в качестве аргумента принимается 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!");
            }
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...