new is unsound, as it lets the user choose the lifetime 'p and then exposes a reference with lifetime 'p without any restriction on it. The user can thus choose 'static and get a &'static mut that really only lives for the lifetime of the PacCell.
let mut s = None;
drop(PacCell::new(String::from("foo"), |p| s = Some(p)));
println!("{s:?}"); // use after free, prints random stuff
Edit: in general you cannot store the child type C with its lifetime, as the actual lifetime is not expressible to the compiler. This is why all self-referential crates either use a macro and internally erase it (self-cell and ouroboros), use some weird trait that generalizes the type over its lifetime (e.g. Yokable in yoke) or are limited to store only a specific kind of type (e.g. the child can only be a reference to some other type). You should consider using one of those approaches otherwise there will likely continue to be issues around your child lifetime.
... but that such new would construct child with a lifetime param that is correct, but cannot be expressed when storing it into the backing struct.
Looking at yoke and self_cell, they so something very similar, but also expose the parent (or cart) which means that child (or yoke) can only borrow cart immutably. This makes me wonder if a sound API even exists for what I'm trying to do here.
Kinda. You do need an existential lifetime (the for<'a> ...) but as you see just doing this is not gonna work because C cannot name that lifetime. In fact referencing C is wrong, a PacCell<Parent, Child<'???>> has no correct lifetime to put in the '??? as it is not borrowing anything external, it is a self-borrow.
Ideally you would be able to say that C is some type generic over 'a, i.e. C<'a>, and then your bound would become for<'a> FnOnce(&'a mut P) -> C<'a>, but unfortunately this syntax is not possible. However you can kinda imitate this with a trait, which is what yoke::Yokable does.
Macro-based crates instead just don't provide a generic API that depends on C as they can just manipulate the AST to fill the lifetime with 'static when storing C internally (of course without ever exposing it to safe code).
I don't see a reason why such an API cannot be sound, though it is surely not compatible with exposing the parent/cart like yoke/self_cell do. So if you don't expose the parent/cart it should be fine.