E0382 with gtk-rs

Hello everyone,

I coded a small programme that shows a warning dialogue when the swap file is used up above a certain threshold. I use gtk-rs to create the dialogue, which can be closed clicking a button. It took a couple of days to "understand" how to do it, thanks to an earlier thread. This is the code I ended up with:

    let application = Application::new(
        Some("com.github.gtk-rs.examples.basic"),
        Default::default(),
    ).expect("failed to initialize GTK application");

    application.connect_activate(|app| {
        let window = ApplicationWindow::new(app);
        window.set_title("Swap is getting full!");
        window.set_default_size(350, 70);

        let window_clone = window.clone();
        let button = Button::with_label("Click to close me");
        button.connect_clicked(move |_| {
            println!("Clicked!");
            window_clone.close();
        });
        window.add(&button);

        window.show_all();
    });

    application.run(&[]);

Using the window object directly in the connect_clicked() action springs up the E0382 error. My first question is: why so? The description of this error seems unrelated, move is not even referred.

And finally, is there a more elegant way of accessing the window object inside the button action? As it stands this code is ugly and verbose.

Thank you.

Can you please post the entire error message?

Did the closure still have the move keyword in it? If so, that’ll force window to get moved into it, and be inaccessible afterwards.

1 Like

Here it is:

error[E0382]: borrow of moved value: `window`
  --> src/main.rs:31:9
   |
22 |         let window = ApplicationWindow::new(app);
   |             ------ move occurs because `window` has type `gtk::ApplicationWindow`, which does not implement the `Copy` trait
...
27 |         button.connect_clicked(move |_| {
   |                                -------- value moved into closure here
28 |             println!("Clicked!");
29 |             window.close();
   |             ------ variable moved due to use in closure
30 |         });
31 |         window.add(&button);
   |         ^^^^^^ value borrowed here after move

error: aborting due to previous error

For more information about this error, try `rustc --explain E0382`.
error: could not compile `swap-warn`.

To learn more, run the command again with --verbose.

That makes sense, the problem is downstream of the connect_clicked() action.

As @MoAlyousef said, your problem is that the window object is captured / moved to the callback handler, so it's no longer available outside it. The move keyword for closures, AFAICT, forces the capture of the environment variables that are references as values. But this is not the case, as the window object is not a reference.

With window_clone you get a cheap Rc to the underlying window that can be kept in the handler and moved to it, without making the original window object unavailable to the outer scope.

Take a look at the glib clone macro. You'll still have some boilerplate code for every closure, and it's doing internally the same thing, but I find it nicer to work with because you're getting rid of a line of code and the clone is sent into the closure with the same name it started with.

I'm on my phone right now, but I can type up an example later if you're interested.

I'm on my second substantial project with gtk-rs. It takes a little getting used to, but once you get the hang of the little idiosyncrasies it's not too bad to work with.

1 Like

Have you tried shadowing the window? As in, let window = window.clone()?

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.