是否可以在不使用类型参数的情况下将Arc <rwlock <&fn()>>传递给函数?

时间:2018-06-19 18:48:35

标签: reference rust trait-objects

我必须将Arc<RwLock<&Fn()>>传递给函数:

use std::sync::{Arc, RwLock};

fn main() {
    let closure = || println!("Hello World");
    let wrapped_closure = Arc::new(RwLock::new(&closure));
    execute(wrapped_closure);
}

fn execute(f: Arc<RwLock<&Fn()>>) {
    let rw_lock_read_guard = f.read().unwrap();
    (rw_lock_read_guard)()
}

Rust Playground

编译失败,并显示错误消息:

error[E0308]: mismatched types
 --> src/main.rs:6:13
  |
6 |     execute(wrapped_closure);
  |             ^^^^^^^^^^^^^^^ expected trait std::ops::Fn, found closure
  |
  = note: expected type `std::sync::Arc<std::sync::RwLock<&std::ops::Fn()>>`
             found type `std::sync::Arc<std::sync::RwLock<&[closure@src/main.rs:4:19: 4:45]>>`

闭包不是Fn吗?

我尝试过:

  • 用参考替换Arc<RwLock>(导致&&Fn())。仅当您在execute()的函数签名中删除一个&符时,此方法才有效,但这并不能真正帮助我,因为出于我不想在此处解释的原因,我需要那些包装。 Rust Playground
  • Fn()函数签名中的execute()移动到where子句中:

    fn execute(f: Arc<RwLock<&F>>) where F: Fn() { /* ... */ }
    

    这也可以,但是,我也不能使用where子句(因为在结构中需要它,但是在结构中没有where子句)。

  • 结合先前的两个想法:传递Arc<RwLock<&&Fn()>>并在函数签名中删除一个&符。那将是我所需要的,但也失败了。
  • wrapped_closure投射到Arc<RwLock<&Fn()>>中(这是解决类似问题here的方法)。这是失败的,因为它是“非原始类型”

是否可以在Rust中传递Arc<RwLock<&Fn()>>而不添加类型参数和where子句?如果是,怎么办?

1 个答案:

答案 0 :(得分:2)

解决方案由Shepmaster提出,并摘自评论。

诀窍是将闭包引用转换为&Fn,将Arc::new(RwLock::new(&closure))替换为Arc::new(RwLock::new( &closure as &Fn() ))。< / p>