Attributi in Rust
Gli attributi in Rust sono metadati applicati a moduli, crate, elementi o espressioni. Controllano compilazione condizionale, derivazione di trait, testing e molto altro.
Sintassi
// Attributo esterno (si applica all'elemento che segue)
#[attributo]
fn funzione() {}
// Attributo interno (si applica all'elemento che lo contiene)
#![attributo]
Derive
Genera automaticamente implementazioni di trait:
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
struct Utente {
nome: String,
eta: u32,
}
#[derive(Debug, Clone, Copy, PartialEq)]
enum Colore {
Rosso,
Verde,
Blu,
}
Trait derivabili dalla std: Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default.
Compilazione Condizionale con cfg
// Compila solo su Linux
#[cfg(target_os = "linux")]
fn solo_linux() {
println!("Sono su Linux");
}
// Compila solo su Windows
#[cfg(target_os = "windows")]
fn solo_windows() {
println!("Sono su Windows");
}
// Con feature flag
#[cfg(feature = "logging")]
fn log(messaggio: &str) {
println!("[LOG] {}", messaggio);
}
// Condizioni multiple
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn solo_linux_64bit() {}
#[cfg(any(target_os = "linux", target_os = "macos"))]
fn unix_like() {}
#[cfg(not(debug_assertions))]
fn solo_release() {}
cfg_attr
Applica un attributo solo quando la condizione è vera:
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
struct Config {
porta: u16,
host: String,
}
Testing
#[test]
fn test_esempio() {
assert_eq!(2 + 2, 4);
}
#[test]
#[should_panic(expected = "overflow")]
fn test_panic() {
panic!("overflow");
}
#[test]
#[ignore]
fn test_lento() {
// Test ignorato di default
}
#[cfg(test)]
mod tests {
use super::*;
// Modulo compilato solo durante i test
}
Controllo Warning e Errori
#[allow(dead_code)] // Silenzia warning per codice inutilizzato
#[allow(unused_variables)] // Silenzia warning per variabili non usate
#[warn(missing_docs)] // Avviso se manca la documentazione
#[deny(unsafe_code)] // Errore se si usa unsafe
#![forbid(unsafe_code)] // Come deny ma non può essere sovrascritto
Deprecazione
#[deprecated(since = "2.0.0", note = "Usa nuova_funzione() al suo posto")]
pub fn vecchia_funzione() {
// ...
}
Attributi per Funzioni
#[inline] // Suggerisce al compilatore di inlinare
#[inline(always)] // Forza l'inlining
#[cold] // Funzione chiamata raramente
#[must_use] // Warning se il valore di ritorno viene ignorato
#[must_use = "Questo Result deve essere gestito"]
fn operazione() -> Result<(), String> {
Ok(())
}
Attributi per Rappresentazione
#[repr(C)] // Layout compatibile con C (per FFI)
struct StrutturC {
a: i32,
b: f64,
}
#[repr(u8)] // Enum con rappresentazione specifica
enum Stato {
Attivo = 0,
Inattivo = 1,
Sospeso = 2,
}
Conclusione
Gli attributi sono uno strumento fondamentale in Rust per configurare il comportamento del compilatore. derive riduce il boilerplate, cfg abilita la compilazione condizionale, e gli attributi di warning/errore aiutano a mantenere la qualità del codice. Familiarizzare con gli attributi comuni è essenziale per scrivere codice Rust idiomatico e ben strutturato.