Email or username:

Password:

Forgot your password?
Joshua Barretto

Something I find myself often wanting to reach for in #rustlang is a `FnPtr` trait: akin to `Fn`/`FnMut`/etc. except where the function is guaranteed to be representable as a function pointer. There are many times when I want to carry something over, say, an FFI boundary without needing the caller of some API to explicitly pass a function pointer.

16 comments
Joshua Barretto

@tranzystorek_io I'm explicitly *not* looking for a function pointer, since that's a usize-sized pointer to code. I'm looking for a trait, since a trait would guarantee static dispatch.

Joshua Barretto

@mo8it A regular function pointer is a runtime value with the same repesentation as `usize` (usually), whereas an `impl FnPtr` would be a zero-sized value that can be turned into a function pointer using some method on the trait.

Raph Levien

@jsbarretto This already exists, there is a "function pointer type" (doc.rust-lang.org/reference/ty), which is distinct from both `dyn Fn` (which can be a closure capturing some of the environment), and an un-nameable concrete function.

play.rust-lang.org/?version=st

Joshua Barretto

@raph Hehe, you're the third person that's responded with 'just use a function pointer'. Unfortunately, a function pointer does not do what I'm describing here: An `impl FnPtr` would be a *zero-sized* type that can be turned into a function pointer through static dispatch. Like this: play.rust-lang.org/?version=st

Joshua Barretto

To be clear to all those responding with 'just use a function pointer': a function pointer specifically *does not* do what I'm looking for. Instead, I'm looking for an API like this: play.rust-lang.org/?version=st

Kornel

@jsbarretto it's going to be zero-sized only in generic structs, but these generally are not fit for use in FFI, so I don't see how it would be useful for FFI in particular.

Joshua Barretto

@kornel It's not specifically useful for passing *over* FFI boundaries, but it allows the construction of safe APIs that wrap FFI and go to and from the same functor on either end.

Joshua Barretto

@kornel Right now, the best approach I have is to have a `assert!(size_of::<F>() == 0);` inside the API and then do an ugly transmute out of thin air on the other side, which I'm certain is at least partially unsound (depending on decisions about whether fn pointers have provenance)

Joshua Barretto

@kornel Also, I can't just remember the function pointer in the enclosing scope: the code I'm writing relies on the final trampoline being a tail call, so any data left in the function body needs to go unused.

I know it seems like a niche case, but this is, I think, the third time (in totally unrelated circumstances) I've wanted to reach for such an API

Go Up