dyn Trait
types like dyn Fn
also have a lifetime, which can be omitted and usually defaults to 'static
. That's where the 'static
was coming from. If you allow the dyn Fn
to be more limited:
struct Finder<'a> {
- find_fn: Box<dyn Fn(&'a str, &'a str)-> Option<usize>>,
+ find_fn: Box<dyn Fn(&'a str, &'a str)-> Option<usize> + 'a>,
find_str: &'a str,
}
impl <'a> Finder <'a> {
- fn new(find_fn: Box<dyn Fn(&'a str, &'a str)->Option<usize>>, find_str: &'a str)-> Self{
+ fn new(find_fn: Box<dyn Fn(&'a str, &'a str)->Option<usize> + 'a>, find_str: &'a str)-> Self{
Self{find_fn, find_str}
}
}
Then the compiler can find its way. Alternatively you can put the trait objects behind shorter lived references:
struct Finder<'a> {
- find_fn: Box<dyn Fn(&'a str, &'a str)-> Option<usize> + 'a>,
+ find_fn: &'a dyn Fn(&'a str, &'a str)-> Option<usize>,
find_str: &'a str,
}
impl <'a> Finder <'a> {
- fn new(find_fn: Box<dyn Fn(&'a str, &'a str)->Option<usize> + 'a>, find_str: &'a str)-> Self{
+ fn new(find_fn: &'a dyn Fn(&'a str, &'a str)->Option<usize>, find_str: &'a str)-> Self{
Self{find_fn, find_str}
}
}
// ...
- let f = Finder::new(Box::new(str::find::<&str>), f_str);
+ let f = Finder::new(&str::find::<&str>, f_str);
And that also works as the dyn Fn
lifetime is inferred to be 'a
in this case as well. See lifetime misconceptions #6 or try adding back the 'static
bound to see the error return.
Why does Alice's solution work then, if it doesn't change the bounds on dyn Fn
? The closures being passed in don't capture anything, so they are in fact 'static
. You can see this by trying to pass in a closure that captures a local reference (i.e. cannot be 'static
).
The indirection of the closures hid the lifetimes that are part of std::find::<'_, _>
that the compiler was struggling with. So in your original example, if you just replace
- let f = Finder::new(str::find::<&str>), f_str);
+ let f = Finder::new(Box::new(|a, b| a.find(b)), f_str);
It is also good enough to compile.
(But Alice's solution, or perhaps a variant using &dyn Fn
, is the much cleaner one.)
I think the compiler is entangling the lifetimes of std::find::<'_, _>
with that of f_str
, as if it could store a copy of f_str
indefinitely (for 'static
), but I don't have a citation nor a good explanation of why.