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.
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.