I have a custom trait that I use as the element type in a slice:
pub trait IConstraint {
  // members here
}
pub struct Scenario<'a> {
  pub constraints: &'a [Box<dyn IConstraint>]
}
I would like to offer an add_constraint method that does a copy-on-write of the slice. Something like this:
impl<'a> Scenario<'a> {
    pub fn add_constraint(&mut self, constraint: Box<dyn IConstraint<TNodeState>>) {
        let mut constraints: Vec<Box<dyn IConstraint<TNodeState>>> = Vec::new();
        constraints.copy_from_slice(self.constraints);
        constraints.push(constraint);
        self.constraints = &constraints;
    }
}
The problem is I get this error:
the trait bound
Box<dyn IConstraint<TNodeState>>: std::marker::Copyis not satisfied the traitstd::marker::Copyis not implemented forBox<dyn IConstraint<TNodeState>>
Ok, so the Box<T> doesn't implement the Copy trait. Fair enough. But how do I address that? Ideally, I'd reuse the boxes or at least the constraints because they are immutable. But if I can't do that due to rust ownership rules, how can I implement the Copy trait on a box type? I've tried various ways and they all produce errors.
This attempt produces "Copy not allowed on types with destructors":
impl<TNodeState> Copy for Box<dyn IConstraint<TNodeState>> {
}
What about Clone? I can switch to constraints.clone_from_slice(self.constraints);, but then implementing the Clone trait on IConstraint produces a bunch of "IConstraint cannot be made into an object" errors.
Even if I could get box to be cloneable, then of course I get the anticipated borrow lifetime flaw from my add_constraint method:
borrowed value does not live long enough
So do I have to throw out my add_constraint function idea altogether and force the owner of my struct to manually copy it? Given my actual struct contains 3 fields, that gets tedious as the owner now has to deconstruct the fields into locals in order to drop the immutable borrow, allowing the original vector to be mutated:
fn add_remove_constraint() {
    let mut scenario = Scenario::<&str, bool, 3_usize>::new(&["A", "B", "C"]);
    let mut constraints: Vec<Box<dyn IConstraint<bool>>> = Vec::new();
    constraints.push(Box::new(SelectionCountConstraint {
        nodes: [1, 2],
        min: 1,
        max: 2,
    }));
    scenario = Scenario {
        constraints: &constraints,
        ..scenario
    };
    assert_eq!(1, scenario.get_constraints().len());
    let nodes = scenario.nodes;
    let selection_state = scenario.selection_state;
    constraints.pop();
    scenario = Scenario {
        constraints: &constraints,
        nodes,
        selection_state,
    };
    assert_eq!(0, scenario.get_constraints().len());
}
 
    