Хранение типов Fn дает ошибку: приведение требует, чтобы ... заимствовано для «статического» - PullRequest
0 голосов
/ 06 апреля 2020

Вот небольшой пример кода, представляющий проблему, с которой я столкнулся в данный момент. CmdMap хранит некоторые логи c из Trait типов, которые должны запускаться клавишей String. Для этой логики c требуется контекст, предоставленный экземпляром Arg. В этом Arg экземпляре нам могут понадобиться изменяемые ссылки на некоторые объекты (представленные здесь Printer).

Вот код:

use std::collections::HashMap;

struct Cmd {}

pub trait Trait<T> {
    fn execute(args: T) -> Result<(), String>;
}

impl<'a> Trait<Arg<'a>> for Cmd {
    fn execute(arg: Arg) -> Result<(), String> {
        arg.printer.print("execute".to_string());
        Ok(())
    }
}

struct Printer {
    name: String,
}

impl Printer {
    pub fn print(&mut self, msg: String) {
        self.name = "print".to_string();
        println!("{}: {}", self.name, msg);
    }
}

struct Arg<'a> {
    pub printer: &'a mut Printer,
}

type Callback<T> = dyn Fn(T) -> Result<(), String>;

struct CmdMap<T> {
    pub map: HashMap<String, Box<Callback<T>>>,
}

impl<T> CmdMap<T> {
    pub fn try_execute(&self, name: String, arg: T) {
        self.map[&name](arg);
    }
}

fn test() {
    let mut map: CmdMap<Arg> = CmdMap {
        map: HashMap::new(),
    };
    map.map.insert("test".to_string(), Box::new(Cmd::execute));

    let mut printer: Printer = Printer {
        name: "".to_string(),
    };

    loop {
        map.try_execute(
            "test".to_string(),
            Arg {
                printer: &mut printer,
            },
        );
    }
}

Компилятор жалуется:

error[E0499]: cannot borrow `printer` as mutable more than once at a time
  --> src/lib.rs:57:26
   |
47 |     map.map.insert("test".to_string(), Box::new(Cmd::execute));
   |                                        ---------------------- cast requires that `printer` is borrowed for `'static`
...
57 |                 printer: &mut printer,
   |                          ^^^^^^^^^^^^ mutable borrow starts here in previous iteration of loop
...
58 |         map.try_execute("test".to_string(), Arg { printer: &mut printer });
   |                                                            ^^^^^^^^^^^^ mutable borrow starts here in previous iteration of loop

Я не понимаю и почему компилятор жалуется здесь. Первая ошибка cast requires that printer is borrowed for 'static не имеет смысла для меня, поскольку я храню Fn типов, которые должны заимствовать printer только на время их выполнения.

Я что-то упустил?

...