当使用带有Rc

时间:2016-08-17 17:05:46

标签: rust

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

引用为“1”的代码,如果取消注释,编译并运行得很好,但引用为“2”的代码无法编译,失败并显示消息:

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

如果我想保持代码结构,我该如何解决这个问题呢?

在我的真实代码中,我想要连接两个特征。其中一个将调用事件的回调,另一个具有处理回调的函数:

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

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

我想用Boo创建一个特征对象,用Rc包裹它,然后以Foo::add_callback

的形式将其传递给|x:i32| Rc::get_mut(&mut boo).unwrap().on_new_data(x)

1 个答案:

答案 0 :(得分:3)

整个错误消息主要是有用:

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

f1更改为接受FnMut并使变量可变允许代码编译:

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

为了将v2参数所需的捕获变量&mut v2变为Rc::get_mut,需要这样做。