I think this would need at least both size_of<F>() == 0 && !needs_drop<F>(). (Which, I think specialization came to mind because I was thinking of Copy + 'static, although you may be right it's nothing to do with trait bounds specifically)
Yeah, excellent point about needs_drop(). (Maybe it would be more elegant using ManuallyDrop…?)
And who knows how many more soundness holes this has – this is why I very sharply advise against seriously trying to achieve this kind of stuff. (Seems like a strange requirement anyway, it's basically a downcasting anti-pattern.)
In this case it's an optimization where I know almost all of the time, the closure is going to be empty, and I'm bundling a single pointer sized value along with it. Boxing for dyn Trait means a memory representation akin to Box<Box<_>>, with this function I could avoid the extra indirection and undersized allocation.
My case is boxing a (Fn(Rc<_>), Rc<_>) to turn into a trait object; with this function I could reimplement the vtable manually and avoid the additional box in my common case of Fn being a Zst, (while still boxing if necessary). It's a specific case optimization somewhat akin to smallstr.