modify source Data in collapsing header - cannot borrow X as mutable more than once at a time

55 Views Asked by At

I'm new to Rust and I can't get my head around a current borrowing issue I have with egui and rust (or maybe what I wan't to do is not possible).

I wan't a List of Items, that are displayed as Collapsable Items. Special should be that there should be a button in the collapsable that adds/modifies the Item list.

I've made a simple sample (based on https://github.com/palmxintreo/egui_template) :

pub struct TemplateApp {
    // Example stuff:
    labels: Vec<String>,
}

impl Default for TemplateApp {
    fn default() -> Self {
        Self {
            // Example stuff:
            labels: Vec::new(),
        }
    }
}

impl TemplateApp {
    /// Called once before the first frame.
    pub fn new(cc: &eframe::CreationContext<'_>) -> Self {
        Default::default()
    }
}

impl eframe::App for TemplateApp {
    /// Called each time the UI needs repainting, which may be many times per second.
    fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
        // Put your widgets into a `SidePanel`, `TopPanel`, `CentralPanel`, `Window` or `Area`.
        // For inspiration and more examples, go to https://emilk.github.io/egui

        egui::CentralPanel::default().show(ctx, |ui| {
            // The central panel the region left after adding TopPanel's and SidePanel's
            ui.heading("eframe template");

            for label in self.labels.iter_mut() {
                let id = ui.make_persistent_id(&label);
                egui::collapsing_header::CollapsingState::load_with_default_open(ui.ctx(), id, false)
                    .show_header(ui, |ui| {
                        ui.label("Head");
                        if ui.button("+").clicked() {
                            self.labels.push("One More".to_string());
                        }
                    }).body( |ui| {
                        ui.label("Body");
                }
            );
            }
        });
    }
}

The compiler complains the following, which I get but don't know how to do it differently.

error[E0499]: cannot borrow `*self.labels` as mutable more than once at a time
  --> src/app.rs:35:38
   |
32 |             for label in self.labels.iter_mut() {
   |                          ----------------------
   |                          |
   |                          first mutable borrow occurs here
   |                          first borrow later used here
...
35 |                     .show_header(ui, |ui| {
   |                                      ^^^^ second mutable borrow occurs here
...
38 |                             self.labels.push("One More".to_string());
   |                             ----------- second borrow occurs due to use of `*self.labels` in closure

0

There are 0 best solutions below