O Rust 1.100 traz a estabilização do tipo never, que melhora a segurança do código, além de novas APIs para melhor controle de alocação de memória. Atualizações no Cargo otimizam o gerenciamento de pacotes, tornando o desenvolvimento mais rápido e confiável.
A versão 1.100 da linguagem de programação Rust acaba de ser lançada com uma novidade aguardada há aproximadamente dez anos: a estabilização definitiva do chamado never type, representado pelo símbolo !.
A atualização marca um momento importante na evolução da linguagem, especialmente porque esse recurso passou por cinco tentativas de estabilização antes de finalmente ser considerado pronto para uso estável.
Além dessa mudança, o Rust 1.100 traz melhorias importantes para o gerenciamento de memória, novos recursos na ferramenta Cargo, mecanismos adicionais de proteção contra ataques à cadeia de suprimentos de software e aperfeiçoamentos no sistema de compilação.
A atualização também introduz o DropGuard, estabiliza partes fundamentais da API de alocadores personalizados e permite identificar dependências que não estão sendo utilizadas em projetos.
As novidades beneficiam principalmente desenvolvedores que trabalham com aplicações de alto desempenho, bibliotecas, sistemas embarcados e projetos que exigem maior controle sobre memória e segurança.
Rust 1.100 finalmente estabiliza o never type após dez anos
O principal destaque do Rust 1.100 é a estabilização do never type, um recurso que estava em desenvolvimento há aproximadamente uma década.
Representado pelo símbolo !, esse tipo especial descreve operações que nunca produzem um valor e, portanto, não retornam normalmente para o fluxo de execução do programa.
Isso acontece, por exemplo, quando uma função encerra o processo, entra em um loop infinito ou provoca uma interrupção por meio de uma operação de pânico.
Em Rust, esse comportamento é chamado de computação divergente.
Na prática, quando o compilador identifica uma expressão cujo resultado é do tipo !, ele sabe que qualquer instrução posicionada depois daquela operação não será executada naquele caminho.
Um exemplo simples é:
fn encerrar() -> ! {
panic!("Operação interrompida");
}
Nesse caso, a função encerrar() nunca retorna um valor convencional. Ela interrompe a execução por meio de um pânico.
Embora o Rust já permitisse utilizar o símbolo ! como tipo de retorno de funções, a versão 1.100 amplia essa possibilidade.
Agora, o tipo pode ser declarado em qualquer posição em que um tipo seja aceito, inclusive dentro de estruturas genéricas.
Por exemplo:
fn resultado<T>(valor: Result<T, !>) -> T {
let Ok(valor) = valor;
valor
}
Nesse exemplo, Result<T, !> representa uma operação que não pode produzir um erro convencional, pois o tipo ! não possui valores possíveis.
Essa característica permite escrever APIs mais precisas e expressar melhor as garantias de funcionamento de determinadas operações.
Por que a estabilização demorou tanto?
A demora está relacionada à complexidade de integrar corretamente o never type ao sistema de inferência de tipos do Rust.
O compilador precisa determinar como esse tipo especial se comporta em diferentes situações, especialmente quando aparece em estruturas genéricas e operações que exigem inferência automática.
Outro desafio envolve a compatibilidade com códigos existentes.
Durante o desenvolvimento, os responsáveis pelo Rust realizaram cinco tentativas anteriores de estabilização que não chegaram ao resultado esperado.
Com o Rust 1.100, esse trabalho finalmente foi concluído.
Uma consequência importante é que o tipo Infallible, utilizado para representar operações que não podem falhar, passa a ser um apelido para !.
Isso permite maior integração entre APIs antigas e novas que utilizam o never type.
API Allocator ganha partes importantes em versão estável
Outra novidade relevante do Rust 1.100 é a estabilização de componentes fundamentais da API Allocator.
Esse recurso permite que desenvolvedores definam alocadores de memória personalizados, oferecendo maior controle sobre a maneira como as aplicações reservam e utilizam memória.
Tradicionalmente, estruturas como Vec e Box utilizam os mecanismos padrão de alocação disponibilizados pela biblioteca da linguagem.
Com a API Allocator, os desenvolvedores podem implementar estratégias específicas para determinadas necessidades.
Isso é especialmente interessante em aplicações que exigem controle rigoroso sobre o consumo de memória, como sistemas embarcados, mecanismos de jogos, servidores e softwares de alto desempenho.
Na versão 1.100, a estabilização contempla a trait Allocator e sua integração com estruturas importantes da biblioteca padrão.
Entre os recursos disponíveis estão:
std::alloc::Allocator;std::alloc::Global;std::alloc::System;Box::new_in;- Suporte a alocadores personalizados em estruturas como
Box,ArceRc.
É importante destacar que essa estabilização representa uma etapa do projeto de expansão da API Allocator. Nem todas as estruturas da biblioteca padrão já oferecem suporte completo a alocadores personalizados.
Mesmo assim, a novidade estabelece uma base importante para futuras melhorias no gerenciamento de memória do Rust.
DropGuard simplifica operações de limpeza e recuperação
O Rust 1.100 também estabiliza o DropGuard, um novo recurso da biblioteca padrão que facilita a execução de operações de limpeza quando uma variável deixa de existir.
A linguagem já possui o mecanismo Drop, utilizado para executar código automaticamente quando um objeto sai de seu escopo.
Entretanto, implementar esse comportamento pode exigir estruturas adicionais quando o desenvolvedor deseja executar uma ação específica ao final de uma função.
O DropGuard simplifica esse processo.
Ele permite associar uma função ou closure a um objeto, garantindo que a operação seja executada quando esse objeto for descartado.
Isso acontece mesmo quando a função termina antecipadamente, utiliza o operador ? ou sofre uma interrupção por pânico.
O recurso também oferece o método dismiss, que permite cancelar a execução da operação de limpeza.
Essa funcionalidade pode ser útil em situações que exigem operações de recuperação, liberação de recursos ou reversão de alterações quando alguma etapa de um procedimento não é concluída corretamente.
Com isso, o Rust 1.100 oferece uma maneira mais simples de implementar determinados padrões de gerenciamento de recursos.
Cargo passa a identificar dependências não utilizadas
O Cargo, gerenciador de pacotes e ferramenta de compilação do Rust, também recebeu melhorias importantes.
Uma das novidades é a capacidade de identificar dependências declaradas no arquivo Cargo.toml que não estão sendo utilizadas pelo projeto.
Isso resolve um problema comum no desenvolvimento de software.
Com o passar do tempo, projetos podem acumular bibliotecas que deixaram de ser necessárias, seja porque determinada funcionalidade foi removida ou porque uma implementação foi substituída por outra.
Mesmo sem utilização, essas dependências podem aumentar o tempo de compilação e tornar a manutenção mais complicada.
A partir do Rust 1.100, o Cargo passa a emitir avisos quando identifica dependências aparentemente desnecessárias.
Um exemplo de mensagem é:
warning: unused dependency `tracing-subscriber`
O aviso ajuda o desenvolvedor a localizar bibliotecas que podem ser removidas do arquivo Cargo.toml.
O recurso é ativado por padrão, mas possui algumas limitações.
A identificação depende da compilação dos diferentes destinos que podem utilizar determinada dependência. Por isso, executar uma verificação limitada a apenas um binário pode não revelar todas as dependências aparentemente não utilizadas.
Além disso, dependências de desenvolvimento, declaradas em dev-dependencies, ainda não são contempladas por esse mecanismo.
Mesmo com essas limitações, a novidade facilita a manutenção de projetos Rust e ajuda a evitar dependências desnecessárias.
Cargo ganha proteção contra pacotes maliciosos recém-publicados
Uma das melhorias mais interessantes do Rust 1.100 está relacionada à segurança da cadeia de suprimentos de software.
O Cargo agora oferece suporte estável ao recurso min-publish-age, também conhecido como período de espera ou dependency cooldown.
A proposta é simples: impedir que o gerenciador de dependências selecione automaticamente versões de pacotes publicadas muito recentemente.
Isso pode ajudar a reduzir a exposição a ataques que utilizam bibliotecas maliciosas distribuídas em repositórios públicos.
Em determinadas situações, pacotes comprometidos são identificados por pesquisadores e sistemas automatizados poucas horas ou dias depois da publicação.
Ao estabelecer um período mínimo de espera, os desenvolvedores ganham tempo para que eventuais problemas sejam identificados antes de incorporar uma nova versão ao projeto.
A configuração pode ser feita no arquivo .cargo/config.toml:
[registry]
global-min-publish-age = "3 days"
Nesse exemplo, o Cargo evita selecionar automaticamente versões publicadas há menos de três dias durante a resolução de dependências.
O período pode ser ajustado conforme as necessidades de cada projeto.
É importante observar que esse mecanismo depende de os registros de pacotes disponibilizarem informações sobre a data de publicação das versões.
Além disso, a proteção não se aplica ao comando cargo install.
O recurso também não substitui auditorias, revisão de dependências ou outras medidas de segurança. Sua função é acrescentar uma camada de proteção contra determinados ataques à cadeia de suprimentos.
Melhorias reduzem conflitos no cache de compilação
Outra mudança do Rust 1.100 envolve a organização dos arquivos temporários utilizados durante a compilação.
O Cargo utiliza diretórios de construção para armazenar bibliotecas e executáveis gerados durante o processo.
Quando um projeto utiliza diferentes configurações, como recursos opcionais, parâmetros de compilação ou diferentes ambientes de desenvolvimento, podem surgir conflitos entre os arquivos armazenados.
Esse problema pode provocar recompilações desnecessárias, utilização de artefatos incorretos e dificuldades para identificar quais arquivos pertencem a determinada configuração.
A nova versão melhora a organização desses diretórios e passa a aplicar de maneira consistente identificadores de configuração aos arquivos gerados.
Com isso, diferentes configurações de compilação conseguem manter seus respectivos artefatos separados.
A mudança é particularmente importante para desenvolvedores que trabalham com vários ambientes, utilizam Git worktrees ou compartilham diretórios de compilação entre diferentes configurações.
Embora seja uma alteração interna, ela prepara o Cargo para futuras melhorias, incluindo mecanismos mais eficientes de limpeza de cache e compartilhamento de artefatos entre projetos.
Rust 1.100 também adiciona outras APIs estáveis
Além das principais novidades, a atualização estabiliza diversas funções e recursos da biblioteca padrão.
Entre os destaques está std::mem::conjure_zst, uma função destinada à criação de valores de tipos de tamanho zero (Zero-Sized Types ou ZST).
Esses tipos não ocupam espaço de memória convencional, mas podem desempenhar funções importantes em sistemas de tipos e APIs que utilizam marcadores.
Como a criação desses valores pode envolver requisitos específicos de segurança, a função é marcada como insegura e exige que o desenvolvedor garanta que sua utilização seja válida.
Outra novidade é Vec::from_fn, que permite construir vetores utilizando uma função responsável por gerar cada elemento.
Também foram estabilizados métodos como str::trim_prefix e str::trim_suffix, que facilitam a remoção de prefixos e sufixos de strings.
Essas melhorias tornam determinadas operações mais simples e ajudam a reduzir a necessidade de implementar funções auxiliares.
Como atualizar para o Rust 1.100?
Desenvolvedores que utilizam o Rustup para gerenciar suas instalações podem atualizar para a nova versão estável executando o seguinte comando no terminal:
rustup update stable
Depois da atualização, é possível conferir a versão instalada com:
rustc --version
O resultado deverá identificar a versão 1.100.0.
Quem ainda não utiliza o Rustup pode consultar as instruções de instalação disponíveis na documentação oficial da linguagem.
Documentação oficial: https://www.rust-lang.org/tools/install
Conclusão
O Rust 1.100 é uma atualização importante para o ecossistema da linguagem, principalmente pela estabilização definitiva do never type após dez anos de desenvolvimento e cinco tentativas anteriores.
Entretanto, as novidades vão muito além desse recurso.
A evolução da API Allocator oferece maior controle sobre o gerenciamento de memória, enquanto o DropGuard simplifica operações de limpeza e recuperação.
No Cargo, a identificação de dependências não utilizadas, a proteção contra pacotes recém-publicados e as melhorias no cache de compilação tornam o desenvolvimento mais organizado e seguro.
Para quem trabalha com Rust, a versão 1.100 representa um avanço significativo na maturidade da linguagem e de suas ferramentas.
A combinação dessas melhorias reforça a proposta do Rust de oferecer desempenho, segurança de memória e ferramentas confiáveis para o desenvolvimento de software moderno.