Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot borrow immutable 'Box' content as mutable

I'm trying to provide a closure via a C callback using a static variable. I was able to get things working with a Fn type, but I'd like to make it work via FnMut to provide users of the library with more versatility.

Here's what I have:

lazy_static! {
    static ref CALLBACK: Mutex<RefCell<Box<FnMut(Result<&str>) + Send>>> = Mutex::new(RefCell::new(Box::new(|_|())));
}

fn wrap_cb<F: Fn(Result<&str>)>(f: Option<F>) -> Option<unsafe extern "C" fn(*mut c_char, size_t)> {
    match f {
        Some(_) => {
            unsafe extern "C" fn wrapped(msg: *mut c_char, len: size_t) {
                let s = std::str::from_utf8(std::slice::from_raw_parts(msg as *const u8, len))
                    .map_err(Error::from);
                let x = CALLBACK.lock().unwrap();
                x.borrow_mut()(s);
            }
            Some(wrapped)
        }
        None => None,
    }
}

This gives the error:

error[E0596]: cannot borrow immutable `Box` content as mutable
  --> src/wpactrl.rs:56:17
   |
56 |                 x.borrow_mut()(s);
   |                 ^^^^^^^^^^^^^^ cannot borrow as mutable
like image 620
spease Avatar asked Jul 25 '26 03:07

spease


1 Answers

It looks like the "cannot borrow immutable Box content as mutable" problem reduces to:

fn invoke(m: &Mutex<RefCell<Box<FnMut()>>>) {
    let r = m.lock().unwrap();
    r.borrow_mut()();
}

I haven't yet figured out why this works, but it does work if changed to:

fn invoke(m: &Mutex<RefCell<Box<FnMut()>>>) {
    let r = m.lock().unwrap();
    let f = &mut *r.borrow_mut();
    f();
}
like image 73
dtolnay Avatar answered Jul 28 '26 06:07

dtolnay



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!