1

I'm trying to create two buttons (btn1, btn2) handling events (simple 'push' aka 'onclick'), they should disable each other

let mut btn1 = button::Button::new(100, 100, 100, 50, "BTN1");
let mut btn2 = button::Button::new(300, 100, 150, 50, "BTN2");

// handle btn1 click
btn1.handle(move |thisBtn, evt| match evt {
    enums::Event::Push => {
        clicked(thisBtn, &mut btn2);
        true
    }
    _ => false,
});

// handle btn2 click
btn2.handle(move |thisBtn, evt| match evt {
    enums::Event::Push => {
        clicked(thisBtn, &mut btn1);
        true
    }
    _ => false,
});

// both buttons should be mutable, or activate/deactivate wont work
fn clicked(thisBtn: &mut button::Button, otherBtn: &mut button::Button) {
    thisBtn.deactivate();
    otherBtn.activate();
}
error[E0382]: borrow of moved value: `btn2`
  --> src\main.rs:18:5
   |
6  |       let mut btn2 = button::Button::new(300, 100, 150, 50, "BTN2");
   |           -------- move occurs because `btn2` has type `Button`, which does not implement the `Copy` trait
...
9  |       btn1.handle(move |thisBtn, evt| match evt {
   |                   ------------------- value moved into closure here
10 |           enums::Event::Push => {
11 |               clicked(thisBtn, &mut btn2);
   |                                     ---- variable moved due to use in closure
...
18 | /     btn2.handle(move |thisBtn, evt| match evt {
19 | |         enums::Event::Push => {
20 | |             clicked(thisBtn, &mut btn1);
21 | |             true
22 | |         }
23 | |         _ => false,
24 | |     });
   | |______^ value borrowed here after move

For more information about this error, try `rustc --explain E0382`.

Okay, I understand that I move the borrowed btn2 so later I can't use it again. So I tried to remove move so btn2 stays in the current scope, but failed:

error[E0373]: closure may outlive the current function, but it borrows `btn2`, which is owned by the current function
kmdreko
  • 42,554
  • 6
  • 57
  • 106
fewrandom
  • 312
  • 1
  • 9

1 Answers1

4

This looks like the classic case for Rc<RefCell<T>>:

let btn1 = Rc::new(RefCell::new(button::Button::new(100, 100, 100, 50, "BTN1")));
let btn2 = Rc::new(RefCell::new(button::Button::new(300, 100, 150, 50, "BTN2")));
let (btn1_clone, btn2_clone) = (Rc::clone(&btn1), Rc::clone(&btn2));
btn1.borrow_mut().handle(move |this_btn, evt| match evt {
    enums::Event::Push => {
        clicked(this_btn, &mut *btn2_clone.borrow_mut());
        true
    }
    _ => false,
});
btn2.borrow_mut().handle(move |this_btn, evt| match evt {
    enums::Event::Push => {
        clicked(this_btn, &mut *btn1_clone.borrow_mut());
        true
    }
    _ => false,
});
BallpointBen
  • 9,406
  • 1
  • 32
  • 62
Chayim Friedman
  • 47,971
  • 5
  • 48
  • 77