Is it safe to extend the lifetime of a reference to a function pointer which is cast to an FnMut?
pub type Handler<T> = dyn FnMut(&T) + Sync + Send;
fn default_handler<'a, T>(_: &'a T) {}
fn a() -> &'static mut Handler<T> {
let a: &mut Handler<T> = &mut default_handler;
// Safety: Is this safe?
let a: &'static mut Handler<T> = unsafe { core::mem::transmute(a) };
a
}
The fn pointer should be static, and the reference shouldn't be pointing to any data on the stack frame itself, so the lifetime seems fine.
The fact that the below code compiles without unsafe, makes me think there is no issue with aliasing.
I don't think the transmute is safe (EDIT: after some thinking, it's probably ok given it's ZST, but I would not bet on it and just use Box::leak(), since Box of ZST doesn't allocate so the optimized code should be pretty much the same). the problem is not aliasing, but static storage:
a 'static reference requires the pointee object have static storage (or "leak"-ed heap storage), but your function is generic, and generic statics are not a thing in rust (as far as I know).
if T is a concrete type (not generic), you don't need to transmute() at all (as your second code snippet shows).
APPENDANT:
the fact that your second code compiles, it has nothing to do with aliasing.
when function item types (not to be confused with function pointer types) are coerced to Fn trait objects, they are stateless (i.e. the Self type is zero-sized), so you can create from thin air as many 'static references as you want, because you don't need actual static storage for zero-sized objects.
If you're not a no_std crate, just use the box leak and avoid unsafe.
Elsewise, after pondering, I think it's fine provided there's no intermediate (sized, local) function pointer involved. Basically you wish &'static mut ZstFunctionItem could be magically conjured/promoted the way &mut [] / &mut [T; 0] can be.
The assert isn't really doing anything anymore in that playground. It's probably fine but I'm not sure how to restore the direct paranoia in a const context with stable Rust. (I only put in a few quick attempts though.)