@zylthinking if you want to play with lifetimes, I recommend that you use function boundaries, which are way more precise / under your control than using a borrow, whose lifetime can be shrunk before assigning the borrow to an invariant structure. Otherwise you will be testing invariance with the attempts from the compiler to let your code compile nonetheless.
Basic example:
struct Context<'a> {
waker: &'a String,
f: *mut fn(&'a ()) -> &'a (),
}
fn with_lifetimes<'_1, '_2> (
c1: Context<'_1>,
c2: Context<'_2>,
)
// where '_1 : '_2, /* if you want to add a `_1 ≥ _2` constraint. */
{
{c1}.f = c2.f; // Error
}