[DISCUSSÃO] O Rust realmente é ruim?
Esse post é, na verdade, uma resposta e também um complemento mais bem avaliado aos meus 2 posts que fiz há mais ou menos 1 ano aqui na plataforma. Também estou voltando a escrever aqui no TabNews depois de um tempão.
Os posts são, especificamente:
- https://www.tabnews.com.br/marcdantas/por-que-o-rust-e-ruim
- https://www.tabnews.com.br/marcdantas/eu-estava-errado-sobre-o-rust
Contexto
Após ter lido os outros dois posts que este deve responder (se não leu, tudo bem. De qualquer forma explicarei aqui), você deve ter percebido o meu grande pé atrás com a linguagem de programação Rust (https://rust-lang.org) e como ela aplica a suposta "solução" para a programação de sistemas.
Os dois posts anteriores mencionam principalmente a questão da sintaxe e da forma que os lifetimes funcionam na linguagem e como deveriam ser melhorados. Eu ainda acredito que estas mudanças são necessárias. Mas aqui vou complementar com mais coisas sobre o design da linguagem em si e como sua filosofia não adequa exatamente ao perfil de uma linguagem realmente preparada para produção séria.
Parte 1: Uso indevido da linguagem
É visto que, nos ultimos tempos, a linguagem Rust sofreu uma grande explosão de popularidade em diversas áreas da programação, o que causou a nova comunidade expandida a se interar ainda mais à linguagem.
A primeira coisa que começou a aparecer são os frameworks Web. Que, ainda que não sejam completamente inúteis, são utilizados em uma linguagem quase que completamente fora do escopo Web e que não comporta o perfil de programador web de nenhuma forma.
Um exemplo muito interessante é o framework Loco. Ele foi feito com a intenção de se parecer ao máximo com o framework Rails (para Ruby). O que claramente não se adequa a uma linguagem de sistemas, que é o Rust.
O uso indevido da linguagem Rust gera uma pressão para os desenvolvedores da linguagem a "generalizar" a linguagem e lentamente deixar de apontar para a direção inicial do design da mesma. O que com certeza causa um overhead absurdo.
Outros exemplos de usos "indevidos" ou anti-naturais do Rust que causam overhead na linguagem:
-
Ferramentas de linha de comando “de escritório”
Muitos CLIs modernos são escritos em Rust apenas pela promessa de segurança e velocidade, mas o tipo de tarefa é semelhante ao que um Java, Go ou mesmo Python fariam sem perda significativa. -
Processamento de dados e pipelines
Rust aparece em projetos de ETL, parsing de arquivos ou servidores de fila. É um ambiente controlado, sem exigência de acesso direto ao sistema. A linguagem funciona, mas não é exatamente seu território natural.
Parte 2: Segurança em troca da sanidade do programador
Rust embarca com seu compilador um sistema denominado "Borrow Checker", que trabalha em conjunto com o Type Checker para garantir a segurança da memória dinâmica alocada durante a execução do programa, com o objetivo de evitar vazamentos de memória (Memory Leak) e outros problemas comuns ao utilizar memória dinâmica.
O borrow checker possui outras funções mas que não contruibuem exatamente para o tema abordado aqui neste post. Caso esteja interessado em saber como o borrow checker funciona, leia o artigo oficial.
Ownership não funciona
O ownership e o borrow checker do Rust estabelecem regras rígidas para evitar erros, mas também cria dependência de um modelo que nem sempre se encaixa em estruturas de dados complexas ou em sistemas que exigem decisões finas sobre desempenho e tempo de vida. O controle manual, apesar de exigir responsabilidade, continua oferecendo uma liberdade que muitas aplicações demandam.
- Controle direto de desempenho
A alocação e liberação podem ocorrer exatamente quando necessário, sem depender de políticas da linguagem ou da interferência de análises do compilador. Isso evita realocações inesperadas, cópias adicionais ou barreiras de sincronização artificiais.
Quantas vezes você já não se deparou tendo que dar
.clone()em tudo para evitar reescrever todo o design do seu programa?
- Responsabilidade explícita
A memória é um recurso físico. Tê-la sob gestão direta mantém as decisões estruturais nas mãos de quem conhece o comportamento do sistema, em vez de depender de restrições de linguagem que funcionam bem apenas em certos estilos de código.
O controle do tempo de vida de memória dinâmica sem depender de designs específico de software é essencial para manter a sanidade de quem desenvolve o software.
Quem já utilizou Rust já passou raiva tendo que escrever e reescrever tantas coisas sem realmente trabalhar na ferramenta que está a desenvolver realmente. Mas só para que o programa em si consiga compilar.
Além de tirar a sua atenção no que você realmente precisa fazer. Ele ainda te força regras estritas sobre como você deve escrever seu código em nome da "segurança".
Parte 3: Javascriptização do Rust
A ideia de que Rust está se “javascriptizando” expressa um incômodo legítimo: a linguagem nasceu com vocação de sistemas, mas seu ecossistema começa a acumular sinais de dispersão. O ponto central não é que Rust esteja virando JavaScript no sentido literal, e sim que o ambiente ao redor da linguagem tende a adotar hábitos que reduzem sua sobriedade técnica. Esse movimento merece crítica justamente porque contrasta com a proposta inicial de Rust: oferecer controle, precisão e parcimônia.
A partir daí, o problema vira excesso de dependências pequenas, gerando cadeias desnecessárias e diluição do propósito técnico. A tendência de encapsular demais também afasta o programador dos custos reais de memória e concorrência, criando um estilo que pouco lembra o trabalho de sistemas. E o uso crescente de Rust em áreas de alto nível reforça esse desvio, espalhando práticas que priorizam conveniência em vez de rigor.
A crítica desta parte do post está mais voltada ao crates.io do que a linguagem em si. Lá a gente encontra muitas bibliotecas extremamente pacatas -- extremamente similar ao que o npm e outros gerenciadores de pacote do JavaScript passam nos ultimos anos (claro que não da forma tão aguda, mas que com certeza não é ideal):
- num_cpus: Retorna o número de CPUs da máquina
- url: Utilitário para parsear URLs
- textwrap: Funções simples para quebrar/formatar texto.
- postfix_assert: Adiciona métodos de assertividade “inline” (ex:
x.assert_some()ao invés deassert!(...)) — basicamente syntax sugar para oassert!. - Entre outros...
Além disso, há críticas recorrentes da comunidade — por exemplo, no fórum da linguagem — quanto à facilidade de adicionar dependências. Um comentário resume bem o problema:
“Whenever I look at a crate on crates.io, I notice that even some very simple crates will have a large amount of dependencies.” (Fonte)
Tradução: "Sempre que analiso um crate no crates.io, percebo que até mesmo alguns crates muito simples possuem uma grande quantidade de dependências."
Parte 4: Coisas boas do Rust
Depois de fazer tantas críticas negativas ao Rust, é bom mencionar as diversas coisas que são definitivamente louváveis na linguagem.
Sistema de Edições
Ao invés de considerar a evolução linguagem em versões (como 1.31.0, 1.56.0, 1.85.0), o Rust classifica em Edições baseadas no ano de lançamento das mesmas (Edição 2018, Edição 2021, Edição 2024), que consideram somente features e mudanças na linguagem ao invés de correções de bugs e mudanças na codebase.
Você pode também utilizar edições iguais para compiladores de diferentes versões e também edições diferentes no mesmo compilador. O que facilita a sua instalação do compilador na sua máquina.
Por exemplo, a versão do compilador X pode conter um bug. Depois de corrigido, a versão do compilador muda para Y mas a edição (a padronização) da linguagem continua igual.
É algo que os compiladores de C e C++ também fazem e chamam de standards (como C99 ou C++23) mas não de forma tão compreensível e organizada como o Rust.
Biblioteca padrão organizada e rica
Diversas tarefas em Rust são muito acomodadas na biblioteca padrão do Rust
de forma compreensível e muito bem documentada, como a forma de Ler arquivos ou de trabalhar com multiplos processos. Além dos recursos de tipagem com os Sum Types que são extremamente úteis (como o Result<T, E> e o Option<T>)
Todas estas características da biblioteca padrão são bastante coerentes para uma linguagem de sistema e providenciam certa comodidade ao utilizar estas ferramentas.
Ferramentas integradas de qualidade
Junto com o compilador. o Rust traz duas ferramentas muito úteis:
- Rustup: Ferramenta de gerenciamento de instalações do Rust e também de geração de documentação local, que ajuda demais no desenvolvimento de ferramentas que não são tão bem documentadas.
- Cargo: Gerenciador de projetos e de pacote muito bem arquitetado e mantido. Com funções de teste unitário e até formatação / correção de código
Conclusão
Fiz esse post para causar mesmo (rsrsrs). Aqui é para ter discussão (obviamente que civilizada) sobre o que cada um acha da linguagem.
Como o criador do C++, Bjarne Stroustrup já dizia:
"There are only two kinds of languages: the ones people complain about and the ones nobody uses."
Então significa que o Rust tá bem!
Obrigado por ler e se sintam livres em comentar por aqui. Obrigado.