Azriel
Azriel

Reputation: 386

Can a trait be passed as a Fn reference or closure

In rust, you can take in a reference to a Fn as documented:

fn call_with_one(some_closure: &Fn(i32) -> i32) -> i32 {
    some_closure(1)
}
let answer = call_with_one(&|x| x + 2);

However I want to write a trait that, if implemented, the Runnable can be passed to anything that expects a Fn(). Is this possible?

trait Runnable {
    fn run(&self);
}

struct MyRunnable;
impl Runnable for MyRunnable {
    fn run(&self) {}
}

struct StructThatTakesClosure<'life> {
    closure_field: &'life Fn(),
}

fn main() {
    // is there a way to change the Runnable trait to automatically match the
    // Fn() interface such that the MyRunnable instance can be passed directly?
    StructThatTakesClosure { closure_field: &|| MyRunnable.run() };
}

I have tried implementing the 3 normally extern calls as default functions but I didn't manage to get it working.

Upvotes: 0

Views: 88

Answers (1)

oli_obk
oli_obk

Reputation: 31173

This is not possible on stable Rust, because the exact definition of the Fn trait is unstable.

On nightly Rust you can implement the Fn traits, but only for concrete types, so it's not very helpful.

impl<'a> std::ops::Fn<()> for MyRunnable {
    extern "rust-call" fn call(&self, ():()) {
        self.run();
    }
}

Upvotes: 3

Related Questions