Self-referencing struct w/ minimum of unsafe

While trying to figure out a way to eliminate a seemingly-redundant lifetime parameter, I had the realization that Rust already has support for one kind of self-referential struct: async blocks.

I wasn’t able to remove the parameter, but I did succeed in making something that looks like it might be able to solve the case where you want to keep an RAII guard long-term: I define a future that acquires whatever guards are necessary and then give an &mut T to a future that will never be ready. As long as that future isn’t cancelled, the borrow checker will make sure that the async code doesn’t violate the &mut guarantees and we can exfiltrate the reference via a raw pointer.

I’m curious if this general approach seems viable, and how it compares to the existing solutions in terms of safety. I also wanted to put this idea out there in case someone else wants to run with it— I don’t have the time to take this from a proof-of-concept to a production-ready crate.

4 Likes

Haven't looked at this stuff in detail yet, but the idea does sound similar to that of the crate mentioned in the last This Week In Rust blog post:

Mainly:

2 Likes

Thanks; I was not aware of this crate. It appears that we both came up with the same basic concept— nolife has more capabilities, and a correspondingly more-complicated API, but the core self-referencing code is strikingly similar to what I’ve written here.


Edit: Apparently, nolife originally had an API similar to this, and some of the complications are there to fix soundness holes. So, in order to keep things simple, Capsule::new will have to remain unsafe, only to ever be used with trusted futures.

That makes mine a building block that crates can build on for specific uses more than a general user-facing solution, which I’m OK with.

1 Like