Programmazione

Rust 1.95.0: cfg_select!, if-let guard nei match e nuove API per Vec e atomici

Dario Fadda Aprile 20, 2026

Il 16 aprile 2026 è uscita Rust 1.95.0, una release che porta novità significative al linguaggio e alla sua libreria standard. Questa versione si segnala in particolare per l’introduzione della macro cfg_select!, il supporto agli if-let guard nei blocchi match, e una serie di nuove API per la gestione della memoria e degli atomici.

Vediamo nel dettaglio cosa cambia e come queste novità influenzano il codice quotidiano dei Rustaceans.

cfg_select!: condizionali di compilazione senza dipendenze esterne

La macro cfg_select! introduce un modo più espressivo per scrivere codice condizionale basato sulla configurazione di compilazione. Si comporta come un match valutato a compile-time sulle condizioni cfg, rimpiazzando di fatto il crate esterno cfg-if che molti progetti Rust usano da anni.

Prima di Rust 1.95, per scrivere codice dipendente dalla piattaforma si usava tipicamente:

// Prima: con cfg-if (dipendenza esterna nel Cargo.toml)
cfg_if::cfg_if! {
    if #[cfg(target_os = "linux")] {
        fn get_system_info() -> String {
            linux_system_info()
        }
    } else if #[cfg(target_os = "macos")] {
        fn get_system_info() -> String {
            macos_system_info()
        }
    } else {
        fn get_system_info() -> String {
            String::from("unknown")
        }
    }
}

Con cfg_select!, la stessa logica si esprime ora senza aggiungere dipendenze al progetto:

// Ora: built-in nella libreria standard
fn get_system_info() -> String {
    cfg_select! {
        target_os = "linux" => { linux_system_info() }
        target_os = "macos" => { macos_system_info() }
        _ => { String::from("unknown") }
    }
}

La sintassi è più pulita e il fatto di essere nella libreria standard elimina la necessità di dichiarare cfg-if nel Cargo.toml. Particolarmente utile per chi sviluppa librerie cross-platform o crate che devono supportare più sistemi operativi e architetture CPU.

if-let guard nei match: pattern matching più espressivo

Rust 1.95 stabilizza gli if-let guard all’interno delle espressioni match, costruendo sulle let chain introdotte in Rust 1.88. Un guard in un match è la condizione if che può seguire un pattern. Finora, questa condizione doveva essere un’espressione booleana semplice. Ora si può usare if let per abbinare pattern aggiuntivi direttamente nella guardia:

fn process(value: Option<Result<i32, String>>) {
    match value {
        Some(x) if let Ok(y) = x => {
            println!("Valore ottenuto: {}", y);
        }
        Some(Err(ref e)) => {
            println!("Errore: {}", e);
        }
        None => {
            println!("Nessun valore");
        }
    }
}

Questo permette di scrivere logica di pattern matching più complessa senza ricorrere a blocchi match annidati. Un caso d’uso pratico è la validazione combinata di metodo HTTP e corpo della richiesta:

fn handle_request(req: &Request) -> Response {
    match req.method() {
        Method::POST if let Ok(body) = serde_json::from_str::<Payload>(req.body()) => {
            process_payload(body)
        }
        Method::POST => {
            Response::bad_request("Payload JSON non valido")
        }
        _ => {
            Response::method_not_allowed()
        }
    }
}

Nota importante sull’esaustività: il compilatore non tiene conto dei pattern negli if-let guard per il controllo di esaustività (exhaustiveness checking). Questo significa che il compilatore non avvertirà se un pattern nell’if-let guard è irraggiungibile. Occorre quindi prestare attenzione quando si usano questi costrutti in match che devono essere esaustivi per correttezza.

Nuove API per Vec, VecDeque e atomici

push_mut e push_back_mut: riferimenti mutabili post-inserimento

Una delle aggiunte più pratiche riguarda i metodi push_mut e varianti per Vec e VecDeque. Questi metodi inseriscono un elemento e restituiscono immediatamente un riferimento mutabile all’elemento appena inserito, eliminando il doppio accesso che prima era necessario:

// Prima: due operazioni separate
let mut v: Vec<String> = Vec::new();
v.push(String::new());
let last = v.last_mut().unwrap(); // secondo accesso necessario
last.push_str("hello");

// Ora con push_mut: un unico accesso, più efficiente
let mut v: Vec<String> = Vec::new();
let elem = v.push_mut(String::new());
elem.push_str("hello"); // riferimento diretto all'elemento appena inserito

Metodi analoghi (push_back_mut, push_front_mut) sono disponibili anche su VecDeque, utile per code e buffer circolari.

update e try_update sugli atomici

I tipi atomici (AtomicUsize, AtomicBool, AtomicI32, ecc.) guadagnano i metodi update e try_update per semplificare i pattern read-modify-write senza dover scrivere manualmente il loop CAS (Compare-And-Swap):

use std::sync::atomic::{AtomicUsize, Ordering};

let counter = AtomicUsize::new(0);

// Incrementa atomicamente, restituisce il vecchio valore
let old = counter.update(Ordering::SeqCst, |x| x + 1);
println!("Valore precedente: {}", old);

// try_update: permette di fallire condizionalmente
// (ritorna Err se la chiusura restituisce None)
let result = counter.try_update(Ordering::SeqCst, |x| {
    if x < 100 { Some(x + 1) } else { None }
});

match result {
    Ok(old_val) => println!("Aggiornato da {}", old_val),
    Err(_) => println!("Limite raggiunto, nessun aggiornamento"),
}

Questi metodi gestiscono internamente il retry loop in caso di contesa tra thread, rendendo il codice più leggibile e meno soggetto a errori.

Stabilizzazioni in const context

Rust 1.95 estende il supporto ai const context per alcune API già stabili, consentendo un uso più ampio della valutazione a compile-time:

  • fmt::from_fn ora utilizzabile in contesti const
  • Metodi di ControlFlow ora const-stabili
  • Nuovi metodi unsafe per puntatori: as_ref_unchecked e as_mut_unchecked
  • Layout::dangling_ptr per manipolazione avanzata della memoria in allocatori custom

Breaking change: JSON target spec non più supportata su stable

Rust 1.95 rimuove il supporto alle specifiche di target in formato JSON sul canale stable. Questa funzionalità era già effettivamente limitata al canale nightly (costruire core richiedeva già nightly), quindi l’impatto pratico è minimo per la maggior parte dei progetti. Chi usa target custom non standard dovrà assicurarsi di usare il canale nightly o di migrare a definizioni di target ufficialmente supportate.

Come aggiornare

Per aggiornare Rust all’ultima versione stabile, basta eseguire:

rustup update stable

Per verificare la versione installata:

rustc --version
# rustc 1.95.0 (xxxxxxxx 2026-04-16)

Conclusioni

Rust 1.95.0 è una release solida che porta miglioramenti trasversali all’ergonomia del linguaggio. cfg_select! riduce la dipendenza da crate esterni per il codice condizionale, gli if-let guard aumentano l’espressività del pattern matching, e le nuove API per Vec e atomici semplificano pattern comuni nella gestione dello stato condiviso in contesti concorrenti.

Nel complesso, questa release conferma la direzione del progetto Rust: migliorare l’ergonomia senza compromettere la sicurezza, incorporando nella libreria standard soluzioni che prima richiedevano crate esterni.

Fonte: Announcing Rust 1.95.0 — The Rust Programming Language Blog

💬 Unisciti alla discussione!


Questo è un blog del Fediverso: puoi trovare quindi questo articolo ovunque con @blog@spcnet.it e ogni commento/risposta apparirà qui sotto.

Se vuoi commentare su Rust 1.95.0: cfg_select!, if-let guard nei match e nuove API per Vec e atomici, utilizza la discussione sul Forum.
Condividi la tua esperienza, confrontati con altri professionisti e approfondisci i dettagli tecnici nel nostro 👉 forum community