简体   繁体   中英

Cannot borrow captured outer variable in an Fn closure when using a closure with an Rc

use std::rc::Rc;

fn f1(cb: Box<Fn(i32) -> i32>) {
    let res = cb(15);
    println!("res {}", res);
}

fn main() {
    let mut v2 = Rc::new(5_i32);

    // 1
    // f1(Box::new(move |x: i32| *v2 + x));

    // 2
    f1(Box::new(move |x: i32| {
        let tmp = *v2;
        *Rc::get_mut(&mut v2).unwrap() = tmp + 1;
        x + *v2
    }));
}

The code referenced as "1", if uncommented, compiles and runs just fine, but the code referenced as "2" does not compile, failing with the message:

error[E0596]: cannot borrow `v2` as mutable, as it is a captured variable in a `Fn` closure

How can I fix this, if I want keep the code structure as it is?

In my real code, I want connect two traits. One of them will call a callback on event, and the other has a function to handle the callback:

trait Foo {
    fn add_callback(&mut self, cb: Box<Fn(i32)>);
}

trait Boo {
    fn on_new_data(&mut self, data: i32);
}

I want to create a trait object with Boo , wrap it with Rc , and pass it to Foo::add_callback in the form of |x:i32| Rc::get_mut(&mut boo).unwrap().on_new_data(x) |x:i32| Rc::get_mut(&mut boo).unwrap().on_new_data(x)

The entire error message is mostly helpful:

error[E0596]: cannot borrow `v2` as mutable, as it is a captured variable in a `Fn` closure
  --> src/main.rs:17:19
   |
17 |      *Rc::get_mut(&mut v2).unwrap() = tmp + 1;
   |                   ^^^^^^^ cannot borrow as mutable
   |
help: consider changing this to accept closures that implement `FnMut`
  --> src/main.rs:15:17
   |
15 |       f1(Box::new(move |x: i32| {
   |  _________________^
16 | |      let tmp = *v2;
17 | |      *Rc::get_mut(&mut v2).unwrap() = tmp + 1;
18 | |      x + *v2
19 | |     }));
   | |_____^

Changing f1 to accept a FnMut and making the variable mutable allows the code to compile:

fn f1(mut cb: Box<FnMut(i32) -> i32>) {

This is needed in order to mutate the captured variable v2 , required by the &mut v2 argument to Rc::get_mut .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM