In rust when a name denotes a function, its type is actually specific to that function:
fn f(){}
The type of f
is not fn()
but fn() {f}
. This actually causing me serious trouble in production code.
I would like to know if there is a way that turns any "specific function type" into a function pointer type without the need to repeat what is the function type. The function would map
fn() {f}
tofn()
fn(i32) {g}
tofn(i32)
- ...
Let's see a simplified example of the issue:
trait X{}
impl<R> X for fn()->R {
}
impl<R,A> X for fn(A)->R {
}
fn f(){}
fn g(i32){}
fn h(f32){}
fn test<T:X>(_:T){}
fn main() {
test(f); // Compiler Error
test(g); // Compiler Error
test(h); // Compiler Error
// All work around implies that library users
// have to write the function type
let a: fn() = f;
test(a);
let b: fn(i32) = g;
test(b);
let c: fn(f32) = h;
test(h);
test(f as fn());
test(g as fn(i32));
test(h as fn(f32));
// I would like something as:
test(to_fn_pointer(f));
test(to_fn_pointer(g));
test(to_fn_pointer(h));
}
About the real case:
I have written a tiny layer on the java native interface to ensure type safety.
When the library written in "native" code is bound to java code manually we have to call RegisterNative.
This function takes as an argument a string representation of the signature of the java function and a pointer to a (rust) function.
To ensure that the function pointer passed to that function and the java function signature matches, I have written a trait that generates directly the "signature" from the function type.
What is bellow is a simplification but it exposes the trouble:
struct NativeMethod{
signature: CString,
function: *const c_void,
}
trait Signature {
fn signature() -> String;
}
impl<R:Signature> Signature for fn()-> {
fn signature() -> CString {
"()" + R::signature()
}
}
impl<R,A> Signature for fn(A) {
fn signature() -> CString {
"(" + A::signature() + ")" + R::signature
}
}
// ... for functions of x arguments
impl Signature for f32 {
fn signature() -> String {
"F".to_owned()
}
}
//...
pub fn declare_native_method<T: Signature + IsFnPointer>(function: T) -> {
NativeMethod {
signature: T::signature(),
ptr: function as * const c_void,
}
}
Unfortunately I cannot call declare_native_method(function)
because i must explicitly convert afunction
to a function pointer. The code is thus verbose and needs duplication of the function type.
X
trait, and in particular how it is used within thetest
function, there may be A Better Way of approaching this problem? – eggyal