1

This code:

//let seen_cell = std::cell::RefCell::new(window_0);
window_0.connect_delete_event(|_, _| {

    //window_0.destroy();
    window.hide();
    Inhibit(true)  
    });

button_0.connect_clicked(|_|{  
    window.show_all(); 
    }  
);

Produces the errors:

error[E0373]: closure may outlive the current function, but it borrows `window`, which is owned by the current function
   --> src/main.rs:192:36
    |
192 |     window_0.connect_delete_event( |_, _| {
    |                                    ^^^^^^ may outlive borrowed value `window`
...
195 |         window.hide();
    |         ------ `window` is borrowed here
    |
help: to force the closure to take ownership of `window` (and any other referenced variables), use the `move` keyword, as shown:
    |     window_0.connect_delete_event( move |_, _| {

error[E0373]: closure may outlive the current function, but it borrows `window`, which is owned by the current function
   --> src/main.rs:199:30
    |
199 |     button_0.connect_clicked(|_|{
    |                              ^^^ may outlive borrowed value `window`
200 |         window.show_all();
    |         ------ `window` is borrowed here
    |
help: to force the closure to take ownership of `window` (and any other referenced variables), use the `move` keyword, as shown:
    |     button_0.connect_clicked(move |_|{

If I try this:

//let seen_cell = std::cell::RefCell::new(window_0);
window_0.connect_delete_event(move |_, _| {

    //window_0.destroy();
    window.hide();
    Inhibit(true)  
    });

button_0.connect_clicked(|_|{  
    window.show_all(); 
    }  
);

I get the errors:

error[E0373]: closure may outlive the current function, but it borrows `window`, which is owned by the current function
   --> src/main.rs:199:30
    |
199 |     button_0.connect_clicked(|_|{
    |                              ^^^ may outlive borrowed value `window`
200 |         window.show_all();
    |         ------ `window` is borrowed here
    |
help: to force the closure to take ownership of `window` (and any other referenced variables), use the `move` keyword, as shown:
    |     button_0.connect_clicked(move |_|{

error[E0382]: capture of moved value: `window`
   --> src/main.rs:199:30
    |
192 |     window_0.connect_delete_event(move |_, _| {
    |                                   ----------- value moved (into closure) here
...
199 |     button_0.connect_clicked(|_|{
    |                              ^^^ value captured here after move
    |
    = note: move occurs because `window` has type `gtk::Window`, which does not implement the `Copy` trait

If I try this:

//let seen_cell = std::cell::RefCell::new(window_0);
window_0.connect_delete_event(move |_, _| {

    //window_0.destroy();
    window.hide();
    Inhibit(true)  
    });

button_0.connect_clicked(move|_|{  
    window.show_all(); 
    }  
);

I get the errors:

error[E0382]: capture of moved value: `window`
   --> src/main.rs:200:9
    |
192 |     window_0.connect_delete_event(move |_, _| {
    |                                   ----------- value moved (into closure) here
...
200 |         window.show_all();
    |         ^^^^^^ value captured here after move
    |
    = note: move occurs because `window` has type `gtk::Window`, which does not implement the `Copy` trait

I have read similar questions but I have not been able to solve this case. How can I solve this in the best way, perhaps by using Arc or similar?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Angel Angel
  • 19,670
  • 29
  • 79
  • 105
  • 1
    The error is related to the lifetime of `window`, which you don't show. More context is necessary. – trent May 10 '17 at 20:39
  • 2
    More specifically, you're trying to do something with the closure that could result in calling `window.hide()` *after* `window` has been destroyed, and similarly with the other closure for `window.show_all()`. You need to somehow prove to the compiler that those methods will only be called while `window` is still alive. – trent May 10 '17 at 20:48

1 Answers1

1

I have solved the above using a macro that I have drawn from some sample projects of gtk-rs

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
            }
        );
    }

Taking the case described I have used it this way:

window_0.connect_delete_event(clone!(window => move |_, _| {

//window_0.destroy();
window.hide();
Inhibit(true)  
}));

button_0.connect_clicked(clone!(window => move |_|{  
    window.show_all(); 

}));

This is the relevant part window_0.connect_delete_event(clone!(window => move. In my case it also applies to button_0.connect_clicked because window Is used later in a similar place

Angel Angel
  • 19,670
  • 29
  • 79
  • 105
  • 1
    Maybe you don't need the complexity of the `clone!` macro, you only need to clone `window` before accessing it, which is fairly standard in Rust. E.g. `window_0.connect_delete_event({let window = window.clone(); move |_, _| { ... }});` Not much more code than using `clone!`, and potentially clearer to the reader not familiar with the macro. – user4815162342 May 16 '17 at 09:06