Rust 1.95: cfg_select! entra na biblioteca padrão e match ganha guardas if let
O Rust 1.95.0 foi lançado em 16 de abril. Quem já tem o Rust instalado via rustup atualiza com rustup update stable. Não é uma versão de grandes manchetes, mas traz duas mudanças de linguagem que vão aparecer no código do dia a dia e uma remoção que merece atenção de quem trabalha com alvos personalizados.
cfg_select!: o cfg-if que virou padrão
Qualquer projeto Rust que precisa se comportar de forma diferente por plataforma acaba recorrendo ao crate cfg-if. O Rust 1.95 estabiliza o macro cfg_select!, que, segundo o anúncio, funciona mais ou menos como um match em tempo de compilação sobre predicados cfg. Ele cumpre o mesmo papel do cfg-if, com outra sintaxe, e expande para o lado direito do primeiro braço cujo predicado é verdadeiro.
O exemplo do post oficial mostra os dois usos, para definir itens e como expressão:
cfg_select! {
unix => {
fn foo() { /* unix specific functionality */ }
}
target_pointer_width = "32" => {
fn foo() { /* non-unix, 32-bit functionality */ }
}
_ => {
fn foo() { /* fallback implementation */ }
}
}
let is_windows_str = cfg_select! {
windows => "windows",
_ => "not windows",
};
O braço _ funciona como fallback, o que deixa explícito o comportamento padrão. Gosto especialmente do uso como expressão: escolher um valor por plataforma em uma linha, sem duplicar blocos #[cfg], deixa o código bem mais legível. É uma dependência a menos para muitos crates.
Guardas if let no match
O Rust 1.88 estabilizou as let chains. O 1.95 leva essa capacidade para dentro das expressões match: agora uma guarda pode usar if let para fazer um segundo casamento de padrão. O exemplo do anúncio:
match value {
Some(x) if let Ok(y) = compute(x) => {
// Both `x` and `y` are available here
println!("{}, {}", x, y);
}
_ => {}
}
Antes, esse padrão exigia aninhar um if let dentro do braço ou reorganizar a lógica. A ressalva importante, destacada no próprio post: o compilador não considera os padrões das guardas if let na verificação de exaustividade do match, assim como já acontece com as guardas if comuns. Ou seja, você continua precisando do braço genérico.
Fim do suporte estável a target specs em JSON
O Rust 1.95 remove o suporte estável a passar uma especificação de alvo personalizada para o rustc. Segundo a equipe, quem usa um toolchain totalmente estável não deve ser afetado, porque compilar a biblioteca padrão, mesmo só o core, já exigia recursos exclusivos do nightly. A equipe está reunindo casos de uso em uma issue de acompanhamento para decidir se alguma forma desse recurso deve ser estabilizada no futuro. Se você trabalha com sistemas embarcados ou kernels e depende disso, vale registrar seu caso lá.
APIs estabilizadas
A lista é longa. Os destaques, para mim:
bool: TryFrompara inteiros, convertendo de forma explícita e falível.- Métodos
updateetry_updateemAtomicPtr,AtomicBoole nos atômicos inteiros, que simplificam laços de compare-and-swap. - O módulo
core::range, comRangeInclusiveeRangeInclusiveIter. core::hint::cold_path, para indicar ao compilador que um caminho é raro.Vec::push_muteVec::insert_mut, além depush_front_mut,push_back_muteinsert_mutemVecDeque, e equivalentes emLinkedList, que devolvem uma referência mutável ao elemento inserido.- Conversões
From,AsRefeAsMutentre arrays deMaybeUniniteMaybeUninitde arrays, e conversões semelhantes paraCell. Layout::dangling_ptr,Layout::repeat,Layout::repeat_packedeLayout::extend_packed.
Também passaram a ser utilizáveis em contexto const o fmt::from_fn e os métodos ControlFlow::is_break e ControlFlow::is_continue.
Minha leitura
O Rust 1.95 é um bom exemplo de como a linguagem evolui: absorvendo padrões que a comunidade já validou em crates, como o cfg-if, e fechando lacunas de ergonomia, como as guardas if let. Nenhuma das duas mudanças é revolucionária, mas ambas eliminam código cerimonial que todo mundo escreve.
Os métodos push_mut parecem pequenos, mas resolvem um incômodo antigo: inserir um elemento e logo em seguida precisar de uma referência a ele. A remoção dos target specs em JSON no estável é a única mudança que pode causar atrito, e mesmo assim para um público restrito que, na prática, já dependia do nightly. Atualização tranquila e recomendada.