Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Correctness

Use checked or saturating arithmetic (checked-arithmetic)

Use checked or saturating arithmetic for operations that could overflow. Prefer explicit overflow handling over silent wrapping:

// Good — overflow is handled explicitly
let total = base.checked_add(offset)
    .ok_or(Error::new(Errno::EOVERFLOW))?;

// Good — clamps instead of wrapping
let remaining = budget.saturating_sub(cost);

// Bad — may silently wrap in release builds
let total = base + offset;

If wraparound behavior is intentional, use explicit wrapping_* or overflowing_* operations and document why wrapping is correct.

Use debug_assert for correctness-only checks (debug-assert)

Assertions verifying invariants that should never fail in correct code belong in debug_assert!, not assert!. debug_assert! is compiled out in release builds, so the check catches bugs during development without costing anything in production.

debug_assert!(self.align.is_multiple_of(PAGE_SIZE));
debug_assert!(self.align.is_power_of_two());

See also: std::debug_assert! and Rust Reference: debug_assertions.

Propagate errors with ? (propagate-errors)

Use the ? operator to propagate errors idiomatically. In kernel code, .unwrap() is rejected wherever failure is a legitimate possibility.

// Good — propagate with ?
let tsc_info = cpuid.get_tsc_info()?;
let frequency = tsc_info.nominal_frequency()?;

// Bad — unwrap hides the failure path
let tsc_info = cpuid.get_tsc_info().unwrap();

See also: The Rust Programming Language, Chapter 9 “Error Handling” and Rust by Example: unpacking options and defaults with ?.