I’ll bite. First off, next time you ask for help, please please please don’t just paste a single long line of code. I’ve gone ahead and formatted it this time, but rustfmt could have done it for you. Also, I suspect this post is better suited for URLO rather than IRLO, but I digress.
use std::any::Any;
use std::borrow::Cow;
use std::sync::Arc;
struct Handler<T> {
f: Arc<dyn for<'a> Fn(&'a mut T) + 'static>,
}
fn make_handler<T>(f: impl for<'a> Fn(&'a mut T) + 'static) -> Handler<T> {
Handler { f: Arc::new(f) }
}
fn outline_fn_trait() {
fn z<'a, 'b>(x: &'a mut Cow<'b, str>) {
println!("{}", x);
}
let x: Handler<Cow<'?, str>> = make_handler(z);
let y: &'? dyn Any = &x;
(y.downcast_ref::<Handler<Cow<'?, str>>>().unwrap().f)
(&mut Cow::Borrowed(&*format!("{}", "Foo")));
}
fn inline_fn_trait() {
fn z<'a, 'b>(x: &'a mut Cow<'b, str>) {
println!("{}", x);
}
let x: &'? (dyn for<'a> Fn(&'a mut Cow<'?, str>) + 'static) = &z;
let y: &'? dyn Any = &x;
(y.downcast_ref::<&(dyn for<'a> Fn(&'a mut Cow<'?, str>) + 'static)>().unwrap())
(&mut Cow::Borrowed(&*format!("{}", "Foo")));
}
The fundamental problem is that Handler<T> contains a pointer to a closure that can take any &'a mut T; thus, the implicit bound for<'a> T: 'a. But, by union of lifetimes, this is equivalent to T: 'static. If you propacate this everywhere, you see that Handler<Cow<T>> must infer as Handler<Cow<'static, T>>. This explains the first error, which you can fix by constructing your Cow like this:
&mut Cow::Borrowed(
Box::leak::<'static>(format!(..).into_boxed_str())
)
Edit: it strikes me as slightly odd that String doesn’t have a leak method directly… shrug.
There is no other way to fix this problem; if you want to stick a closure in Handler without making Handler generic in the longest lifetime that can be passed to f, then it can only take T: 'static types. I suspect he type you really want is
struct Handler<'ctx, T> where T: 'ctx {
callback: Arc<dyn for<'a: 'ctx> Fn(&'a mut T) + 'ctx>,
}
where 'ctx is the lifetime of whatever thing the handler is being registered for. Presumably, the register method of your event loop or whatever should look like this:
pub fn register_handler(&mut self, &mut Handler<T>)
where all the lifetimes are deduced to be 'self.
Now, why does the second example work? I believe this is just with Fn being treated specially by the typechecker; if I instead wrote
type MyFn<T> = dyn for<'a> Fn(&'a mut T) + 'static;
(y.downcast_ref::<&MyFn<Cow<str>>>().unwrap())
(&mut Cow::Borrowed(&*format!("{}", "Foo")));
we see the same error, since MyFn has an implicit where T: 'static clause. I suspect that the fact that this even worked in the first place is a bug, since I would expect dyn for<'a> Fn(&'a mut T) + 'static to impose the same where clause.