3 ms·
I'm curious what things you consider to be half-baked about Rust async. I've used Rust async extensively for years, and I consider it to be the cleanest and mo
by Pauan 3y ago
I'm curious what things you consider to be half-baked about Rust async.
I've used Rust async extensively for years, and I consider it to be the cleanest and most well designed async system out of any language (and yes, I have used many languages besides Rust).
- tel 3y agoAsync traits come to mind immediately, generally needing more capability to existentially quantify Future types without penalty. Async function types are a mess to write out. More control over heap allocations in async/await futures (we currently have to Box/Pin more often than necessary). Async drop. Better cancellation. Async iteration.
- Pauan 3y ago> Async traits come to mind immediately, I agree that being able to use `async` inside of traits would be very useful, and hopefully we will get it soon. > generally needing more capability to existentially quantify Future types without penalty Could you clarify what you mean by that? Both `impl Future` and `dyn Future` exist, do they not work for your use case? > Async function types are a mess to write out. Are you talking about this? fn foo() -> impl Future<Output = u32> Or this? async fn foo() -> u32 > More control over heap allocations in async/await futures (we currently have to Box/Pin more often than necessary). I'm curious about your code that needs to extensively Box. In my experience Boxing is normally just done 1 time when spawning the Future. > Async drop. That would be useful, but I wouldn't call the lack of it "half-baked", since no other mainstream language has it either. It's just a nice-to-have. > Better cancellation. What do you mean by that? All Futures/Streams/etc. support cancellation out of the box, it's just automatic with all Futures/Streams. If you want really explicit control you can use something like `abortable`, which gives you an AbortHandle, and then you can call `handle.abort()` Rust has some of the best cancellation support out of any async language I've used. > Async iteration. Nicer syntax for Streams would be cool, but the combinators do a good job already, and StreamExt already has a similar API as Iterator.
- kprotty 3y ago> That would be useful, but I wouldn't call the lack of it "half-baked", since no other mainstream language has it either. It's just a nice-to-have. Golang supports running asynchronous code in defers, similar with Zig when it still had async. Async-drop gets upgraded from a nice-to-have into an efficiency concern as the current scheme of "finish your cancellation in Drop" doesn't support borrowed memory in completion-based APIs like Windows IOCP, Linux io_uring, etc. You have to resort to managed/owned memory to make it work in safe Rust which adds unnecessary inefficiency. The other alternatives are blocking in Drop or some language feature to statically guarantee a Future isn't cancelled once started/initially polled.
- pkolaczk 3y ago> Golang supports running asynchronous code in defers, similar with Zig when it still had async. So does Rust. You can run async code inside `drop`.
- kprotty 3y agoTo run async in Drop in rust, you need to use block_on() as you can't natively await (unlike in Go). This is the "blocking on Drop" mentioned and can result in deadlocks if the async logic is waiting on the runtime to advance, but the block_on() is preventing the runtime thread from advancing. Something like `async fn drop(&mut self)` is one way to avoid this if Rust supported it.