Issues with mutable borrows when attempting dynamic dispatch

Heya. I'm currently trying to figure out how a basic plugin system would like in Rust. I have the following code, but I'm getting errors over multiple mutable borrows which makes sense. However, how can I circumvent this? Code is on Rust Playground.

You could only borrow the other fields of Editor in Custom:

trait Custom {
    fn update(&mut self, name: &mut String, position: &mut usize);
}

#[derive(Default)]
struct Editor {
    name: String,
    position: usize,
    myeditor: Option<Box<dyn Custom>>,
}

impl Editor {
    fn new() -> Self {
        Self {
            myeditor: Some(Box::new(MyEditor::default())),
            ..Self::default()
        }
    }
    fn run(&mut self) {
        loop {
            if let Some(myeditor) = &mut self.myeditor {
                myeditor.update(&mut self.name, &mut self.position);
            }
        }
    }
}

#[derive(Debug, Default)]
struct MyEditor();

impl Custom for MyEditor {
    fn update(&mut self, name: &mut String, position: &mut usize) {
        *name = String::from("bruh");
        println!("{}", name);
    }
}

fn main() {
    Editor::default().run();
}

You need to remove myeditor from self so that you don't keep borrowing self. Since you already have myeditor as an Option, the easiest way is to take() it:

if let Some(myeditor) = &mut self.myeditor.take() {
    myeditor.update(self);
}

You need to then put myeditor back in afterwards, but since its boxed, there's no cost to moving it each time.

1 Like

After changing the code to the following:

if let Some(myeditor) = &mut self.myeditor.take() {
    myeditor.update(self);
    self.myeditor = Some(Box::new(myeditor));
}

I get the following error:

error[E0277]: the trait bound `&mut Box<(dyn Custom + 'static)>: Custom` is not satisfied
  --> src/main.rs:23:38
   |
23 |                 self.myeditor = Some(Box::new(myeditor));
   |                                      ^^^^^^^^^^^^^^^^^^ the trait `Custom` is not implemented for `&mut Box<(dyn Custom + 'sta
tic)>`
   |
   = note: required for the cast to the object type `dyn Custom`

Why doesn't this work?

That doesn't work because you are trying to rebox myeditor when putting it back in. I think you can remove the &mut referencing in the if let and deal with myeditoras an owned value, then put it back without reboxing (though you do need the Some).

Smooth solution. Thanks!