So we're not sure how much help we're gonna get out of this, but as we understand it, the basic idea of Pin is to define a contract: "You'll not be moved."
So for example, if we had a hexchat plugin crate, with a Plugin trait (which implies Default) we could let plugin = Box::pin(T::default()); where T: Plugin, and then plugin.init(...), and then the code can assume it won't be moved again.
And that's great! But it feels unhelpful.
We have this crate - which does not use Pin - and like, hypothetically, if we wanted to let plugins take &self into hooks, well, we can't. We believe there are at least 2 issues to this:
We're not sure how we'd actually pass the appropriate lifetime on the self: Pin<&Self> such that the hooks can borrow from it. We've heard this is a hard problem, and that there are talks about 'self because of it, so we're not gonna worry about this part for now.
Drop seems like it would be an issue. Let's talk more about this one.
If we understand correctly, there is no "safe Rust" solution to &self in hooks, because hooks are owned by a Plugin, and if the hooks have a Drop type which refers to (parts of) the Plugin, they could observe references to a (partially) deinitialized value, which is UB.
So, if we understand corretly, the best we could ever do, if we wanted to go this route, is provide a guarantee for unsafe Rust to rely on?
To my very non expert understanding: Pin mostly exists to make async work (faster). It doesn't mean you can't move the target, (you are already not allowed to move out of something that has a reference to it, afterall), it means you are providing a way of asking if you can move the content (with Unpin), eg it doesn't contain any pointers or mutexes or the like that would break if they were moved by the async runtime / complier at runtime. (I could easily be wrong about this!)
Self referencing doesn't really match up with that, at least without complier magic like async functions get. For now, Rc/Arc weak references are probably the least bad option.
The idea of Pin is to allow user-code to promise unsafe code in your crate that the user-code will not move some struct that the user-code owns. If you don't need a promise of exactly that form, then you don't need Pin.
Regarding 'self lifetimes and so on, it's important to understand that Pin exists to make some specific kinds of unsafe code correct. It does not make the code safe. Self-referential structs using Pin will still need unsafe code.
One thing that comes to mind is that although Pin could be used for this, another way to achieve the same thing is to make the methods on the trait unsafe, and write that the plugin may not be moved in the safety requirements section of the trait's documentation.