How to implement FnOnce


#1

I want to implement FnOnce, but failed. And, I even can’t find any tips…Rust is hard, very hard to learn, as The book is too simple to create a true project.

struct Handler {
    count:i32,
}

impl FnOnce<()> for Handler {

    type Output = i32;

    extern "rust-call" fn call_once(self, args: ()) -> i32 
    {
        1
    }
}

fn main() {
    let h = Handler {count:1};
    h();
}

It says

src/main.rs:9:5: 12:6 error: rust-call ABI is subject to change
src/main.rs: 9 extern “rust-call” fn call_once(self, args: ()) -> i32
src/main.rs:10 {
src/main.rs:11 1
src/main.rs:12 }

What should I do?


#2

You can’t implement FnOnce (or Fn or FnMut), because it’s currently defined using "rust-call" which is an unstable implementation detail.

If you really want to implement it/them yourself, you’ll need to use a nightly compiler (and add a #![feature(core, unboxed_closures)] attribute to your crate source), plus accept that your code could be broken by compiler changes at any time.


#3

Thanks.

So many rules I don’t know.


#4

We’ve all been there, trying to dig into a concept and being thwarted by some detail that we weren’t privy to at the beginning. Sometimes it helps to dig into the actual Rust source code on Github and read the actual implementation source. Most of the language and standard library details can be found within libcore and libstd.

It can be tedious, but that (in my opinion) is the most optimal way to learn. Chin up, you’ll learn it in no time! And when you do, contribute your knowledge back to the community as a blog post or whatnot. Part of the hassle of using a new language is the lack of edge-case documentation. Bringing light to these dark corners will go a long way to helping new users of the language!


#5

Why don’t you just use a closure? They automatically implement FnOnce, even on stable.


#6

He might want Handler to be statically sized without resorting to boxing.


#7

I want to implement a thread pool, and I found a crate named threadpool, It uses FnBox, then I read the source code of FnBox…

impl<'a,A,R> FnOnce<A> for Box<FnBox<A,Output=R>+'a> {
    type Output = R;

    extern "rust-call" fn call_once(self, args: A) -> R {
        self.call_box(args)
    }
}

Then, I want to implement my FnBox…Then I was confused by the complier…