How to make a global changable hashmap or slice?

In my situation, I had different type rules. And when I got a rule, and run collect_patterns_recursive to get other rule, and then run collect_patterns_recursive in other rule...

So

  • If I don't clone the rule, it will cause the borrowing issue.
  • If clone the rule, it will cause performance issue.

Does someone have a good solution?

use std::borrow::BorrowMut;
use dyn_clone::{clone_trait_object, DynClone};
use std::collections::HashMap;

trait BasicRule: DynClone {
    fn id(&self) -> i32;
    fn collect_patterns_recursive(&mut self, container: &mut RuleContainer,);
}

clone_trait_object!(BasicRule);

#[derive(Clone)]
pub struct Rule { id: i32, }

#[derive(Clone)]
pub struct BeginRule { rule: Rule }

impl BeginRule {
    pub fn new(id: i32) -> Self {
        BeginRule { rule: Rule { id } }
    }
}

impl BasicRule for BeginRule {
    fn id(&self) -> i32 { self.rule.id }

    fn collect_patterns_recursive(&mut self, container: &mut RuleContainer) {
        let other_rule_id = 0;
        let mut rule = container.get_rule(other_rule_id).clone();
        rule.collect_patterns_recursive(container);
    }
}

#[derive(Clone)]
pub struct EmptyRule { }

impl BasicRule for EmptyRule {
    fn id(&self) -> i32 { 0 }
    fn collect_patterns_recursive(&mut self, container: &mut RuleContainer) {

    }
}

pub struct RuleContainer {
    pub rules: HashMap<i32, Box<dyn BasicRule>>,
}

impl RuleContainer {
    fn default() -> Self {
        RuleContainer {
            rules: Default::default(),
        }
    }

    pub fn get_rule(&mut self, pattern_id: i32) -> &mut Box<dyn BasicRule> {
        return self
            .rules
            .get_mut(&pattern_id)
            .unwrap();
    }

    pub fn register_rule(&mut self, result: Box<dyn BasicRule>) -> i32 {
        let id = result.id();
        self.rules.insert(id, result);
        id
    }
}

fn main() {
    let mut container = RuleContainer::default();
    let id = 1;
    container.register_rule(Box::new(EmptyRule { }));
    container.register_rule(Box::new(BeginRule::new(1)));

    let mut rule = container.get_rule(1).clone();
    rule.collect_patterns_recursive(&mut container);
}