Rocket v0.5 Release Candidate(rocket.rs)
rocket.rs
Rocket v0.5 Release Candidate
https://rocket.rs/v0.5-rc/news/2021-06-09-version-0.5-rc.1/
7 comments
I write this as an active contributor to Actix-Web, and working on a Rust web framework of my own. Rust is amazing, the guarantees and performance it provides are incredible. However, the async ecosystem is immature. Without GATs and TiiT, you cannot have async fns in traits, making writing middleware and services much more difficult to write. Along with that, async and lifetimes, or unmet Send + Sync bounds leads to long, often confusing compiler errors. Current runtimes require you to think about blocking. While this is not as much of a problem for those who have dealt with this from other languages, I cannot count the number of times I have seen someone write `tokio::spawn(async { users::get(conn) })` - blocking the executor. Mixing async and sync, or even worse, mixing tokio and async-std is a pain. Compared to Go and Javascript, Rust will be hard, there is no denying that. I love Rust. As someone who understands and writes lower-level async code, I do think it has a place in the web world, and there is active work being done by the async-wg to improve ergonomics. However, it's not there as a general-purpose server-side language yet, and I am not sure it will ever be. Sure, use it for certain services, or side projects you want to have fun with. Is there ever going to be a "Rails for Rust"? Probably not, but people will and are trying :)
Great comment. Thanks for sharing your lived experience. Technology does evolve. But it's always helpful to have in-depth perspectives.
The fact that it's not easy to write any sort of Async and standard sync interop is incredibly brutal. It's fairly obvious that Async was an afterthought and not given the same love and attention as the rest of the language.
Async is a major focus. Whether the benefit has been worth the (very high) cost is another question.
How big an issue is this practice? I only have superficial knowledge of Actix (currenly reading https://www.zero2prod.com/ which covers Actix) but I don't think the lack of GATs and TiiT was raised.
What does TiiT refer to? Can't seem to search for it.
Type alias impl trait [0]. Async fns return an existential type `impl Future`. You cannot return that type in traits yet (on stable), so getting a concrete return type requires dynamic dispatch and a heap allocation. On top of that, async fns capture from any references they take as arguments. To do that in traits would require GATs (generic associated types) [1]:
[0]: https://github.com/rust-lang/rust/issues/63063
[1]: https://github.com/rust-lang/rust/issues/44265
[2]: http://smallcultfollowing.com/babysteps/blog/2019/10/26/asyn...
impl Foo for Bar {
// GAT ↓ TiiT ↓
type Output<'a> = impl Future<Output = Foo> + 'a;
fn foo<'a>(&'a self) -> Self::Output<'a> { ... }
}
The above is possible on nightly, whereas on stable you would have to box the future, and because you can't capture from self, you would have to use a ref counted pointer or clone the parts of self you need. Eventually, this entire transformation would allow for async fns directly in traits, but that is probably a long way off [2].[0]: https://github.com/rust-lang/rust/issues/63063
[1]: https://github.com/rust-lang/rust/issues/44265
[2]: http://smallcultfollowing.com/babysteps/blog/2019/10/26/asyn...