TLDR; It is not possible to implement traits for fn() types to be used without casting (which I consider impractical).
The long story:
First off a little background: I'm experimenting with Rust by implementing language bindings with Rust-looking APIs. I started making bindings with Lua, I know there are at least two other bindings of Lua already but I'm mainly doing it for personal experience to learn how far can I go in regards to sort of meta programming.
I knew about the experimental nature of Rust from the beginning and I was willing to try my best to cope with the moving changes of the pre-1.0.0 phase. I mostly think it did great for the language.
My whole point revolves around this basic API sketch, which may not be the best but I see no reason for it to be impossible: having a method that can to push any object which can be represented and used on the other language to it's stack, like this:
struct VM {...}
impl VM {
pub fn push<T: ToVM>(&mut self, value: T) { ToVM::push(self, value); }
}
trait ToVM { fn push(vm: &mut VM, value: Self); }
With that in mind I only need to impl ToVM for every type that can be pushed into the VM using its native API, namely foreign functions.
For all basic data types that's perfectly reasonable, even for Vectors and HashMaps that's doable.
But for functions and closures it was only until before the coercions rfc that it was doable.
For simplicity I'll only talk about functions but it all applies to closures with a few adjustments.
When functions had denotable types it was ok, I could use lua's API to push a lua closure, which is a C function with some associated data, the data would be the transmuted fn and the C function a wrapper which transmuted the data back into a fn and called it. Effectively pushing a Rust function into the lua's stack which could be called within the lua context. (which is exactly the technique Selene uses on C++). Which won't require the user to change their function just so it works with my implementation, nor require any casting because of a language limitation.
But regardless of the internals used to make that work, it was possible simply because the raw function types were usable.
The higher picture for me is that functions should not have unique types the same way ints don't have unique types. There is the Int and Float traits but you also have the iXX and fXX types, the same should be with functions, Fn() traits and also usable fn() types. Because it should be possible to implement a trait for functions which only applies if you can work with their underlying type.
To me that's a key issue for a system language.
What most intrigues me is what lead to making functions have their own types, I don't know the implementation but I think it only makes it more complicated.
What I'm interested in knowing is:
- Am I missing something, is my point not valid?
- What's the motivation for unique fn types?
- Will there be any coercions to address this (or if that's possible)?
- I read somewhere that functions will change from pointer like to zero sized like, is that true? Wouldn't that make it even worse?