cargo clippy în Rust

Cargo și rustup Clippy 1.29 (componenta clippy, instalată implicit de rustup)

Analizează codul cu sute de reguli (lints) și semnalează greșeli frecvente, cod ineficient sau neidiomatic, cu sugestii de corectare.

Sintaxă
cargo clippy                          # verifică și dă sfaturi
cargo clippy --fix                    # aplică automat sugestiile sigure
cargo clippy -- -D warnings           # avertismentele devin erori (CI)
#[allow(clippy::nume_regula)]         // dezactivează o regulă local

Ce face cargo clippy

Clippy este un „profesor” pentru codul Rust: compilează proiectul ca cargo check și aplică în plus peste 700 de reguli. Găsește bucle scrise greu (for i in 0..v.len()), comparații inutile (len() == 0 în loc de is_empty()), clonări inutile, posibile bug-uri și cod care poate fi simplificat.

Fiecare avertisment are un nume (de exemplu clippy::needless_range_loop), un link spre explicația regulii și, de obicei, o sugestie de cod. cargo clippy --fix aplică automat sugestiile sigure.

Regulile sunt grupate: clippy::all (implicit), clippy::pedantic (mai stricte), clippy::nursery (noi). O regulă se poate dezactiva local cu #[allow(clippy::nume)] sau pentru tot proiectul în secțiunea [lints.clippy] din Cargo.toml.

Exemple

Exemplul 1: Patru sfaturi pentru un program scurt

Codul se compilează fără avertismente obișnuite, dar Clippy găsește patru lucruri de îmbunătățit, fiecare cu soluția lui.

// src/main.rs
fn main() {
    let note = vec![9, 7, 10];
    let mut total = 0;
    for i in 0..note.len() {
        total = total + note[i];
    }
    if note.len() == 0 {
        println!("Nicio notă");
    }
    println!("Total: {total}");
}

$ cargo clippy

Rezultat în terminal

    Checking salut v0.1.0 (/home/ana/proiecte/salut)
warning: the loop variable `i` is only used to index `note`
 --> src/main.rs:4:14
  |
4 |     for i in 0..note.len() {
  |              ^^^^^^^^^^^^^
  |
  = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.99.0/index.html#needless_range_loop
  = note: `#[warn(clippy::needless_range_loop)]` on by default
help: consider using an iterator
  |
4 -     for i in 0..note.len() {
4 +     for <item> in &note {
  |

warning: manual implementation of an assign operation
 --> src/main.rs:5:9
  |
5 |         total = total + note[i];
  |         ^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `total += note[i]`
  |
  = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.99.0/index.html#assign_op_pattern
  = note: `#[warn(clippy::assign_op_pattern)]` on by default

warning: length comparison to zero
 --> src/main.rs:7:8
  |
7 |     if note.len() == 0 {
  |        ^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `note.is_empty()`
  |
  = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.99.0/index.html#len_zero
  = note: `#[warn(clippy::len_zero)]` on by default

warning: useless use of `vec!`
 --> src/main.rs:2:16
  |
2 |     let note = vec![9, 7, 10];
  |                ^^^^^^^^^^^^^^ help: you can use an array directly: `[9, 7, 10]`
  |
  = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.99.0/index.html#useless_vec
  = note: `#[warn(clippy::useless_vec)]` on by default

warning: `salut` (bin "salut") generated 4 warnings (run `cargo clippy --fix --bin "salut" -p salut -- ` to apply 3 suggestions)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.41s

Exemplul 2: Codul după aplicarea sfaturilor

Aceeași logică, scrisă idiomatic. cargo clippy nu mai are nimic de semnalat, iar programul rulează la fel.

fn main() {
    let note = [9, 7, 10];
    let mut total = 0;
    for nota in &note {
        total += nota;
    }
    if note.is_empty() {
        println!("Nicio notă");
    }
    println!("Total: {total}");
}

Rezultat

Total: 26

Greșeli frecvente

  • Dezactivezi o regulă peste tot (#![allow(clippy::all)]) pentru că un sfat pare inutil. Citește explicația din link; dacă nu se potrivește, dezactiveaz-o doar în locul respectiv.
  • Rulezi cargo clippy --fix cu modificări nesalvate în git: Cargo refuză (working directory contains uncommitted changes), ca să nu amesteci modificările. Fă commit sau adaugă --allow-dirty.

Comenzi înrudite

  • cargo check: Verifică dacă proiectul se compilează (tipuri, borrow checker) fără să producă executabilul. Este mult mai rapid decât cargo build.
  • cargo fmt: Formatează automat tot codul proiectului după stilul oficial Rust (indentare, spații, acolade), cu rustfmt.
  • atribute (#[derive], #[cfg], #[allow]): Informații pentru compilator scrise cu #[…] deasupra unui element: generează cod (derive), aleg codul compilat (cfg) sau schimbă avertismentele.
  • for … in: Parcurge pe rând fiecare element al unui interval, al unei colecții sau al unui iterator.