El ecosistema de herramientas de Rust va mucho más allá del compilador y Cargo. clippy con sus lints avanzados, cargo-audit para vulnerabilidades conocidas, cargo-flamegraph para perfilar CPU, miri para detectar comportamiento indefinido y cargo-deny para política de dependencias forman juntos un pipeline de calidad que pocos lenguajes pueden igualar.
clippy avanzado: pedantic, nursery y allow selectivo
clippy incluye grupos de lints con distintos niveles de agresividad. El grupo clippy::pedantic activa advertencias útiles pero que pueden generar falsos positivos; clippy::nursery añade lints experimentales. Puedes silenciar lints individuales con #[allow] donde el aviso no es aplicable.
// Activar grupos completos desde la línea de comandos:
// cargo clippy -- -W clippy::pedantic -W clippy::nursery
// O en código (afecta a todo el crate):
#![warn(clippy::pedantic)]
#![warn(clippy::nursery)]
#![allow(clippy::module_name_repetitions)] // silenciar un lint concreto
// Lints útiles de pedantic:
fn suma_positivos(v: &[i32]) -> i32 {
// clippy::pedantic sugiere usar filter_map en lugar de filter+map
v.iter().filter(|&&x| x > 0).sum()
// Sugerencia: v.iter().filter(|&&x| x > 0).sum()
}
// #[allow] localizado solo donde hace falta:
#[allow(clippy::cast_possible_truncation)]
fn truncar_a_u8(n: u32) -> u8 {
n as u8 // clippy lo marcaría sin el allow
}
// clippy::nursery: redundant_clone, cognitive_complexity...
fn procesar(datos: Vec<String>) -> Vec<String> {
datos.into_iter()
.filter(|s| !s.is_empty())
.map(|s| s.to_uppercase())
.collect()
}
cargo-audit: vulnerabilidades RUSTSEC
cargo-audit compara tu Cargo.lock con la base de datos de vulnerabilidades de RustSec y avisa si alguna dependencia tiene CVEs conocidos. Es el paso más básico de seguridad en un pipeline CI.
// Instalación y uso:
// cargo install cargo-audit
// cargo audit
// Ejemplo de salida cuando hay un advisory:
// error[RUSTSEC-2023-0072]: Potential deadlock in a specific pattern
// --> Cargo.lock:...
//
// Para ignorar un advisory concreto (con justificación documentada):
// En .cargo/audit.toml:
// [ignore]
// RUSTSEC-2023-0072 = "No usamos la API afectada (ver issue #42)"
// En CI, falla el pipeline con:
// cargo audit --deny warnings
cargo-flamegraph: perfilado de CPU
cargo-flamegraph genera un flamegraph SVG interactivo a partir de muestras de perf (Linux) o DTrace (macOS). Permite identificar visualmente qué funciones consumen más tiempo de CPU sin tocar el código fuente.
// Instalación:
// cargo install flamegraph
// Configurar símbolos de debug manteniendo optimizaciones (Cargo.toml):
// [profile.release]
// debug = true
// Generar flamegraph de un binario:
// cargo flamegraph --bin mi-binario
// O de un benchmark criterion:
// cargo flamegraph --bench mi_bench -- --bench
// El SVG generado muestra la pila de llamadas.
// Las barras más anchas son las funciones que más tiempo consumen.
// Haz clic en cualquier función para hacer zoom.
// Para perfilar con perf directamente (más control):
// perf record -g --call-graph dwarf cargo run --release
// perf script | stackcollapse-perf.pl | flamegraph.pl > out.svg
miri: detectar comportamiento indefinido
miri es un intérprete de MIR (la representación intermedia de Rust) que ejecuta el programa simulando la memoria y detecta comportamiento indefinido, accesos fuera de bounds, uso de memoria no inicializada y violaciones del modelo de aliasing de Rust.
// Instalación (requiere nightly):
// rustup +nightly component add miri
// cargo +nightly miri test
// Ejemplo: miri detecta esto como UB aunque clippy no lo marque
unsafe fn sumar_raw(ptr: *const i32, n: usize) -> i32 {
let mut suma = 0;
for i in 0..n {
suma += *ptr.add(i); // miri verifica que todos los accesos son válidos
}
suma
}
// miri también detecta:
// - Data races en código unsafe con hilos
// - Aliasing inválido (&mut y & al mismo dato)
// - Fugas de memoria en código unsafe
// - Acceso a memoria liberada (use-after-free)
fn main() {
let datos = [1i32, 2, 3, 4, 5];
let suma = unsafe { sumar_raw(datos.as_ptr(), datos.len()) };
println!("Suma: {suma}"); // miri: OK si los índices son correctos
}
cargo-deny y cargo-udeps
cargo-deny aplica políticas sobre las dependencias del workspace: prohíbe licencias incompatibles, fuentes no permitidas y advisories de seguridad. cargo-udeps detecta dependencias declaradas en Cargo.toml que no se usan en el código.
// cargo-deny: configurar en deny.toml
// [licenses]
// allow = ["MIT", "Apache-2.0", "BSD-2-Clause", "BSD-3-Clause"]
// deny = ["GPL-3.0"]
//
// [advisories]
// db-path = "~/.cargo/advisory-db"
// db-urls = ["https://github.com/rustsec/advisory-db"]
// vulnerability = "deny"
//
// Ejecutar:
// cargo deny check
// cargo-udeps: encontrar dependencias no usadas
// cargo install cargo-udeps
// cargo +nightly udeps
// Resultado típico:
// unused dependencies:
// `mi-crate v0.1.0`
// ??? dependencies
// ??? "rand" (unused)
Integra todas estas herramientas en un script de CI que ejecute: cargo clippy -- -D warnings, cargo audit --deny warnings, cargo deny check, y cargo test. Con este pipeline básico capturas la mayoría de errores de calidad y seguridad antes de que lleguen a producción, sin necesitar herramientas externas ni configuración compleja.
