Um plano de quatro anos para async Rust
Async/await em Rust continua profundamente polarizador: alguns desenvolvedores o elogiam por viabilizar serviços de rede altamente concorrentes e eficientes, enquanto outros o acham ergonomicamente desajeitado, “viral” pelas codebases e mal adequado para casos de uso embarcados ou mais simples. Os comentários reagem a um roteiro proposto de quatro anos para async em Rust, debatendo peças ausentes como async em traits, generators, um `block_on` padrão, traits agnósticos a runtime e se a std deveria incluir um executor padrão. Por trás dos pontos técnicos está uma tensão mais ampla entre as raízes de Rust em programação de sistemas e seu uso crescente para web e backends de serviços, além da frustração com o ritmo lento e conservador de estabilizar grandes recursos da linguagem.
“Contágio” de async e contornos
- Muitos reclamam que, se uma dependência é async, “tudo precisa ser async”.
- Outros respondem que é possível isolar o async:
- Subindo um runtime pequeno (por exemplo, Tokio single-threaded, smol, pollster) e usando
block_on. - Executando código async em uma thread dedicada e se comunicando via canais.
- Subindo um runtime pequeno (por exemplo, Tokio single-threaded, smol, pollster) e usando
- Os críticos respondem que isso ainda traz runtimes pesados e dependências extras, o que importa para tempos de build, confiança e ambientes restritos.
Ergonomia, complexidade e experiência no mundo real
- Alguns consideram o async Rust um grande defeito: viral, pouco intuitivo, pesado em lifetimes, com erros ruins do compilador, closures difíceis e interações estranhas com
async_trait. - Outros relatam anos de uso tranquilo em grandes codebases de produção, argumentando que as reclamações são exageradas e muitas vezes vêm de experiência limitada ou desatualizada.
- Há cansaço com argumentos recorrentes de “async é difícil/ruim” que ignoram nuances do design ou do artigo ligado.
Domínios: servidores vs embarcados e sistemas
- Para serviços de rede com alta concorrência (servidores HTTP, proxies intensivos em banco de dados), muitos dizem que async é indispensável para desempenho previsível e escalabilidade.
- Para sistemas embarcados e de baixo nível, há uma divisão:
- Alguns evitam async completamente (preferindo RTOSs, atores, threads, interrupções, DMA, loops de eventos).
- Outros elogiam frameworks como Embassy como substituto leve de um RTOS e para estruturação ergonômica de tarefas.
Runtimes, domínio do Tokio e stdlib
- Tokio efetivamente “venceu” o ecossistema; muitos crates dependem fortemente dele (locks, channels, spawn).
- Alguns veem isso como um problema cultural e arquitetural e querem traits agnósticos a runtime (AsyncRead/Write, Stream, spawn, locks, channels) em
std. - As propostas incluem:
- Um executor mínimo ou
block_onemstd(possivelmente no estilo pollster). - Não tornar Tokio o runtime padrão; segundo relatos, tanto os mantenedores de Rust quanto os de Tokio se opõem a isso.
- Um executor mínimo ou
Modelos de concorrência: threads, async, green threads
- Há debates sobre se async deve ser um recurso da linguagem ou um problema de biblioteca/ferramentas.
- Alguns argumentam que thread-por-conexão é bom o suficiente para a maioria das cargas e mais simples; async ajuda principalmente com enormes números de tarefas concorrentes limitadas por IO.
- Outros dizem que green threads / fibers (goroutines estilo Go, Loom do Java) oferecem melhor DX do que async colorido, sem infectar APIs.
- Contra-argumento: Rust removeu green threads no passado; reintroduzi-las com o modelo de segurança do Rust e restrições de incorporabilidade não é trivial.
Lacunas de design da linguagem e planos
- Pontos de dor mencionados: complexidade de Pin/Unpin, falta de generators/iterators async, história fraca para async em traits (melhorando em breve), ergonomia ausente para async closures, falta de async drop, ausência de tipos lineares/infracíveis.
- Alguns querem um trait
Movee semântica de imutável por padrão para simplificar async; outros são cautelosos. - Generators são vistos como intimamente relacionados a async e desejáveis, mas seu retorno no mundo real é debatido.
Ritmo de evolução do Rust e governança
- Alguns criticam a estabilização “glacial” (por exemplo,
block_onem std, generators, correções mais profundas em async), querendo prazos de 6 meses em vez de planos de vários anos. - Outros defendem a estabilização lenta e conservadora porque as features são, na prática, para sempre e precisam estar certas antes de serem congeladas.