How to solve "cannot borrow captured outer variable in an `Fn` closure as mutable" (gtk-rs)


#1

Hello guys,
i’m fairly new to rust. I have a small problem. Let’s see this code snippet: (I removed unimportant code)

// make moving clones into closures more convenient
macro_rules! clone {
    (@param _) => ( _ );
    (@param $x:ident) => ( $x );
    ($($n:ident),+ => move || $body:expr) => (
        {
            $( let $n = $n.clone(); )+
            move || $body
        }
    );
    ($($n:ident),+ => move |$($p:tt),+| $body:expr) => (
        {
            $( let $n = $n.clone(); )+
            move |$(clone!(@param $p),)+| $body
        }
    );
}

pub struct MainWindow{
    [...]
    imgbox: ImageBox,
    current_date: chrono::NaiveDate
}

impl MainWindow {
    pub fn new(gtkapp: &gtk::Application) -> Self {
        [...]
        let previous_button: gtk::Button = builder.get_object("previous_button").unwrap();
        let next_button: gtk::Button = builder.get_object("next_button").unwrap();

        [...]

        next_button.connect_clicked(clone!(imgbox, current_date => move |_| {
            current_date.add_assign(chrono::Duration::days(1));

            let img = MainWindow::get_img_from_date(&current_img_date);
            imgbox.set_img(&img);
        }));

        Self { window, stack, imgbox, current_date}
    }

I get this rust error message:

error[E0596]: cannot borrow captured outer variable in an `Fn` closure as mutable
  --> src/mainwindow.rs:60:13
   |
60 |             current_date.add_assign(chrono::Duration::days(1));
   |             ^^^^^^^^^^^^
   |

I have no idea how i can “fix” this. think it’s pretty normal to change a value (“current_date”), in a closure / callback function. What’s the proper way to solve this in rust?


#2

Try
$( let mut $n = $n.clone(); )+


#3

connect_clicked requires an Fn closure which means it cannot mutate anything (via normal means). You can put the date into a RefCell and mutate via that.