Reputation: 24547
I have a few implementations of a function that I would like to test. To do that cleanly, I want to put references to them into an array and call them one by one. Due to recent syntax changes, to do this, you need to first explicitly cast functions to function references with correct type signatures. Since the syntax you use to declare a function is different from its actual type, this is a non-trivial task.
How do you figure out the type of a reference to a Rust function with non-trivial signature (e.g. it involves generics, lifetimes, takes another function, etc.)?
A particular function (which I wrote) was declared with signature:
pub fn take_while2<'a,T,F:Fn(&T)->bool >(initial: &'a [T], predicate: F) -> Option<&'a [T]> {...}
Upvotes: 2
Views: 1378
Reputation: 59045
You can't, at least, not with that function.
First of all, you have can't have a generic variable. That is, x
can't depend on T
. To take a simpler example:
fn test<T>(_: &T) { unimplemented!() }
fn main() {
let x: fn(&u8) = test;
}
This works because the compiler can infer the concrete type T
is (in this case, u8
). So why can't you do that? Because of F
. You're asking for a closure type, and closure types are anonymous; no matter what you do, you can't name one. If you managed to get the type system to infer the closure type, it would only be valid for exactly one specific closure. Much like functions, each closure has its own unique type, even if it is literally the same. Unlike functions, closures don't have a common base type you can use.
It's hard to give any recommendations without knowing what it is you're actually trying to accomplish. To take a stab in the dark, however, you might want to try something like:
pub fn take_while2<'a,T>(initial: &'a [T], predicate: Box<Fn(&T) -> bool>) -> Option<&'a [T]> { // '
// ...
}
fn main() {
let functions: Vec<for<'a> fn(&'a [u8], Box<Fn(&u8) -> bool>) -> Option<&'a [u8]>> = vec![take_while2]; // '
// ...
}
Note the use of for<'a>
which is a higher-ranked lifetime, which has the same function as the 'a
generic parameter for the take_while2
definition. Also note that this syntax does not work for type arguments.
Credit to Shepmaster for reminding me that you can also use &Fn(&T) -> bool
instead of a boxed closure. That lifts the requirement of a heap allocation for the caller.
This will also require you to box any closures you want to pass to predicate
.
Upvotes: 2