It's not a matter of minimalism or simplicity, it's a matter of different priorities. Rust's stackless async support is suitable for systems like microcontrollers, and the design reflects that.
It's not a matter of minimalism or simplicity, it's a matter of different priorities. Rust's stackless async support is suitable for systems like microcontrollers, and the design reflects that.
This is the argument you hear, but how does it play out in practice? I don't know of any async runtimes that don't use Arcs, you can't use the async trait crate (boxed futures=allocations) and you don't have the escape hatches needed (Arcs) when you get too deep in type-hell. To this day, I haven't heard any embedded folks praise async Rust. I'm by no means an embedded expert, but if I were to do embedded I'd likely go with a plain old event loop to be safe.
Getting zero-cost (static only) stackless async was a huge flex, and I'm very impressed with the proof of concept. I'm just wondering whether it actually targeted the intended demographic.
The thing that makes async runtimes complicated is handling multithreading in an intelligent way, and that's not something that worries most embedded engineers.
That said, it is very cool, and does work well, if you want to do it. I think for many projects it would make sense. For our requirements, synchronicity works, and so we’re sticking with it, but folks on my team use it for other things, just not in the specific context we’re in.
The key is that nothing in async rust requires dynamic allocation. This is in opposition to C++‘a async stuff, which can in theory optimize away the allocations that are required, but you’re relying on the optimizer to do that. Our particular environment allows us to be 100% static, all the time, and so we’re pursuing that route as far as it can go.
I've only worked on embedded development using C++, but I didn't really encounter any issues writing (admittedly, somewhat simple) device drivers with no heap whatsoever.
Tangent: How feasible would it be to have a language where the required stack space for all function invocations is statically known at compile time, just as the sizes of Rust futures are statically known? I guess this would be even harder, because with async functions, the compiler only has to store the state of the function in a statically sized structure when it reaches an await point. But I'm guessing that running out of stack is a common problem when developing for microcontrollers.