assert! și debug_assert! în Rust

Verifică o condiție la rulare și dă panică dacă este falsă. debug_assert! face verificarea doar în modul debug, nu și în release.

Sintaxă
assert!(conditie);
assert!(conditie, "mesaj {}", valoare);
debug_assert!(conditie);            // verificat doar în modul debug

Ce face assert! și debug_assert!

assert!(conditie) verifică o condiție care trebuie să fie adevărată. Dacă este falsă, dă panică cu mesajul assertion failed: conditie (textul exact al condiției) sau cu mesajul tău, dacă îl dai după condiție, cu sintaxa lui format!. Se folosește în teste și pentru a verifica presupuneri importante în cod (precondiții).

debug_assert! are aceeași formă, dar este verificat doar când debug_assertions este activ: la cargo build/cargo run și la teste, nu și la --release. Este potrivit pentru verificări costisitoare (de exemplu „vectorul este sortat”) pe care nu vrei să le plătești în programul final.

Pentru comparații de egalitate, assert_eq! și assert_ne! sunt mai utile, pentru că afișează ambele valori. Spre deosebire de C, assert! rămâne activ și în release; doar debug_assert! dispare.

Exemple

Exemplul 1: Verificări care trec

Toate condițiile sunt adevărate, deci programul continuă normal. debug_assert! verifică aici că lista primită de căutarea binară este sortată (verificare lentă, doar în debug).

fn cauta(sortate: &[u32], tinta: u32) -> Option<usize> {
    debug_assert!(sortate.is_sorted(), "lista trebuie să fie sortată");
    sortate.binary_search(&tinta).ok()
}

fn main() {
    let coduri = [1001, 1005, 1020, 1100];
    assert!(!coduri.is_empty());
    assert!(coduri.len() <= 1000, "prea multe coduri: {}", coduri.len());
    println!("1020 este pe poziția {:?}", cauta(&coduri, 1020));
    println!("1003: {:?}", cauta(&coduri, 1003));
}

Rezultat

1020 este pe poziția Some(2)
1003: None

Exemplul 2: O verificare care eșuează

Procentul 120 nu respectă condiția, deci programul se oprește cu mesajul dat. Fără mesaj propriu, ar fi apărut textul condiției: assertion failed: procent <= 100.

fn aplica_reducere(pret: f64, procent: u32) -> f64 {
    assert!(procent <= 100, "reducere invalidă: {procent}%");
    pret * (100 - procent) as f64 / 100.0
}

fn main() {
    println!("{}", aplica_reducere(200.0, 15));
    println!("{}", aplica_reducere(200.0, 120));
}

Rezultat (programul se oprește cu panică)

170

thread 'main' (14809873) panicked at main.rs:2:5:
reducere invalidă: 120%
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Greșeli frecvente

  • Pui în debug_assert! cod cu efecte (de exemplu debug_assert!(v.pop().is_some())). În release, tot apelul dispare, deci și efectul.
  • Folosești assert! pentru validarea datelor introduse de utilizator: o greșeală de tastare oprește programul. Pentru date externe returnează Result cu un mesaj clar.
  • Scrii assert!(a == b) în teste: la eșec vezi doar assertion failed: a == b, fără valori. assert_eq!(a, b) le afișează pe amândouă.

Comenzi înrudite

  • assert_eq! și assert_ne!: Verifică dacă două valori sunt egale (assert_eq!) sau diferite (assert_ne!); la eșec, panica afișează ambele valori.
  • panic!: Oprește firul de execuție curent cu un mesaj de eroare. Se folosește pentru situații care nu ar trebui să apară niciodată (bug-uri).
  • teste (#[test]): O funcție marcată cu #[test] este un test automat: cargo test o rulează și raportează dacă a trecut sau a dat panică.
  • cfg!: Evaluează la compilare o condiție de configurare (sistem de operare, mod debug, feature Cargo) și o transformă în true sau false.