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!

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.