Rust matching on enum members behind mutable reference

So here is a snippet of code


pub struct SavedItemCard {
    saved_item: SavedItem,
    button_state: button::State,
}


impl SavedItemCard {
    pub fn new(saved_item: SavedItem) -> Self {
        Self {
            saved_item,
            button_state: button::State::new(),
        }
    }

    fn view_submission_card(&mut self, submission: &SavedSubmission) -> Element<CardMessage> {
        Container::new(
            Column::new()
        ).into()
    }

    fn view_comment_card(&mut self, _comment: &SavedComment) -> Element<CardMessage> {
        Container::new(
            Column::new()
        ).into()
    }

    fn view(&mut self) -> Element<CardMessage> {
        match self.saved_item {
            SavedItem::Comment(comment) => self.view_comment_card(&comment),
            SavedItem::Submission(submission) => self.view_submission_card(&submission),
        }
    }
}

The idea behind what I am trying to do is I match on the enum member and depending on the value call the appropriate function. The reason I am passing the inner struct of the enum as an argument is so that I don't match again within the function.

But the compiler tells me:
error[E0507]: cannot move out of self.saved_item.0 which is behind a mutable reference

It then suggests to borrow the self.saved_item, but that leads to other issues such as cannot borrow *self as mutable more than once.

I don't really see what I am doing wrong here. Is there a better, correct way of doing this?

You can't in general call a method like so:

    self.method_that_takes_ref_mut_self(&self.component);

As if you could, inside the method, you would have an aliased unique borrow path (&mut self covers &mut self.component).

Things will go easier if it's possible to either remove the component from self (perhaps temporarily), or if the method can take &self instead of &mut self (to remove the unique borrowing constraints). If not, you'll probably need some sort of refactoring to pass in mutable references to only the parts of self that are needed for the method, in such a way that they don't overlap with the saved_item field. (E.g. some sort of view struct.)

Thanks for the very informative blog post link

Yeah, I have to use mut because the GUI framework that I am using needs a mutable reference to the button state, which I will be using in the view functions.

Since I don't have that many fields yet, the free function solution seems much more easier to me. But yeah, overall this seems like a much bigger problem.

EDIT
Alternatively I can refactor the SavedItemCard struct into an Enum with inner structs that have their own state and view functions.

This way there will be no partial borrowing. There will be some code duplication but that's fine, and it seems way more scalable if I keep adding more state for the views.

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.