The above code reasonably fails because there is no 'b such that &'b str: for<'a> From<&'a str> as I understand it. But is it possible to achieve this with the following constraints?
use From trait.
the string passed is owned by check() stack.
If we are allowed to use a different trait, what would it be?
The problem is that Fn(&str) is a shorthand for the HRTB ("higher-ranked trait bound") for<'a> Fn(&'a str), which is not a special case of Fn(T). Since check intends to pass a borrow of a local variable to F in the Fn(&str) case, it's not possible to instead expect Fn(&'a str) for any concrete lifetime 'a, since local variables cannot be borrowed for the duration of an external lifetime parameter.
The best approach might be to introduce your own trait here and put it as a trait bound on F. Conceptually, something like
However this only works with function pointers and you'd need to cast functions to function pointers (and accept potential runtime-overhead).
If you want things to work with all Fn-implementing types including function items (and closures ) this no longer works; we cannot generically implement this trait for all Fn-implementors, since (at least in theory / with unstable Rust features) there could be overlapping implementations; i.e. a type F could be bothFn(String) and Fn(&str) at the same time. In this case, introducing a dummy parameter and relying on type inference may help:
trait StringFunction<T> {
fn call(&self, s: String);
}
fn check<F, T>(f: F)
where
F: StringFunction<T>
{
let my_str = String::from("hello");
f.call(my_str);
}
impl<F> StringFunction<String> for F where F: Fn(String) {
fn call(&self, s: String) {
self(s)
}
}
impl<F> StringFunction<&str> for F where F: Fn(&str) {
fn call(&self, s: String) {
self(&s)
}
}
fn main() {
fn fn_1(_: &str) {}
fn fn_2(_: String) {}
check(fn_1);
check(fn_2);
}