Hacker News new | past | comments | ask | show | jobs | submit login

Some of the pain inflicted by async Rust is incidental, not due to this GC choice. Pin is the biggest culprit.

Pin exists so that references captured in Futures may be implemented via raw pointers. This implies that a Future contains pointers to itself, hence Pin.

The cost of Pin is that it forces you to write unsafe code as a matter of course, the so-called pin-projections. [1] Look at the requirements for structural pinning: they are quite complicated.

References captured in Futures probably could have been implemented differently: base + offset, or relocations, or limit what can be captured, or always Box the state for a Future that captures a reference. Those would have avoided a GC and been even safer, since it wouldn't require unsafe code on the part of struct implementors.

1: https://doc.rust-lang.org/std/pin/#projections-and-structura...




I don't think base + offset would have worked because then references would have to be codegen'd differently depending on whether they're in a future or not; this would have impacted separate compilation as you can pass references to other functions (including across FFI). Relocations only work at load time (either dynamic linking or link time), so they wouldn't work. Limiting what can be captured was tried with the old futures crate and it was a real nuisance. Boxed futures violate the zero-cost abstractions principle, which is the reason why many Rust users are using the language in the first place.

Pin is an evil, but it's the least evil of the possible options.


"Relocations" was meant as an analogy. The idea is, each time a future is entered, it checks if its base pointer has changed. If so, it fixes up its own pointers, similar to how a linker fixes up self-pointers in a dynamic library. There's obvious limitations but it would handle common cases efficiently.

Anyways when I first tried async, I encountered structural pinning immediately, and I was surprised to learn that users are just expected to write unsafe code to participate in this system. Maybe it really is the best tradeoff but seems at odds with the rest of the language.


I don't think it's possible for a future to enumerate all the references that belong to it. At the very least it's not obvious to me how that's possible to implement, due to the way lifetime subtyping works.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: