---
title: "0.11 Warnings, lints, and Clippy"
description: "Rust compiler warnings, why they're on by default, the underscore convention, and the Clippy and rustfmt tools."
url: "https://learnrust.net/chapter-0/warnings-lints-and-clippy/"
last_updated: "2026-06-11"
---

# 0.11 Warnings, lints, and Clippy

So far we've talked about compiler *errors*: your program breaks a rule, the compiler explains, no executable is produced. But the compiler has a second, gentler voice. A **warning** means: this code is legal, I compiled it, and I think something about it deserves your attention.

Here's a program that earns one:

```rust
fn main() {
    let unused = 5;
    println!("Hello!");
}
```

This compiles and runs fine. But building it gets you:

```
   Compiling warn_demo v0.1.0 (/Users/you/projects/warn_demo)
warning: unused variable: `unused`
 --> src/main.rs:2:9
  |
2 |     let unused = 5;
  |         ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused`
  |
  = note: `#[warn(unused_variables)]` (part of `#[warn(unused)]`) on by default

warning: `warn_demo` (bin "warn_demo") generated 1 warning (run `cargo fix --bin "warn_demo" -p warn_demo` to apply 1 suggestion)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.11s
```

Look at the anatomy, because every Rust warning is shaped like this: the `warning:` line states the concern, the arrow points into your source at the exact spot, a `help:` note proposes a concrete fix, and the `note:` names the rule producing it. Then the build *finishes anyway*; warnings never stop compilation. The proposed fix here (renaming the variable to `_unused`) is a real convention: a leading underscore tells both the compiler and human readers "yes, this is deliberately unused," and the warning stands down.

Why warn at all over something legal? Because legal-but-pointless code is usually a symptom: a variable you *meant* to use but didn't is the visible half of a bug, the way one shoe by the roadside implies a story. The compiler can't know your intent, so it compiles the code and raises an eyebrow.

> **Key insight**
>
> Errors are for code that breaks the rules. Warnings are for code that follows the rules while looking like a mistake. The compiler resolves the ambiguity by doing its job and telling you its doubts, which is exactly what you'd want from a sharp colleague.

If you've programmed C or C++ before, notice what you did *not* have to do: turn the warnings on. There, meaningful diagnostics hide behind flags every beginner has to be told about (`-Wall` and friends, a lesson-length topic on learncpp.com, this course's C++ counterpart). Rust ships with its warnings on and its defaults sane, and the culture treats them as signal. The tutorials, the tools, and the libraries all assume a warning is something you *handle*.

> **Best practice**
>
> Deal with warnings as they appear: fix the cause, or (where the code is truly intentional) silence that one instance deliberately, underscore-style. The reason is practical: a build that's normally silent makes every new warning impossible to miss, while a build with forty stale warnings hides the one that matters. Warning number forty-one is invisible.

> **For advanced readers**
>
> Teams often go further and make warnings *fail* the build, typically in their continuous-integration checks (the robots that build every proposed change). Rust can do that with a flag or a one-line attribute. The trade-off to know before copying that idea into your own projects: new compiler releases occasionally introduce new warnings, so "warnings are fatal" means a compiler update can break a build that worked yesterday. Standard practice is strict robots, forgiving laptops.

## Clippy: the warnings connoisseur

The compiler's built-in warnings are the conservative tier. Rust also ships **Clippy**, a separate analyzer with hundreds of additional **lints**: checks for code that's legal, often even sensible-looking, but unidiomatic, needlessly slow, or subtly error-prone. Run it like this, on any project:

```bash
cargo clippy
```

Give it something to disapprove of:

```rust
fn main() {
    let on = true;
    if on == true {
        println!("running");
    }
}
```

```
    Checking clippy_demo v0.1.0 (/Users/you/projects/clippy_demo)
warning: equality checks against true are unnecessary
 --> src/main.rs:3:8
  |
3 |     if on == true {
  |        ^^^^^^^^^^ help: try: `on`
  |
  = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.96.0/index.html#bool_comparison
  = note: `#[warn(clippy::bool_comparison)]` on by default

warning: `clippy_demo` (bin "clippy_demo") generated 1 warning (run `cargo clippy --fix --bin "clippy_demo" -p clippy_demo -- ` to apply 1 suggestion)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.42s
```

Clippy's point: comparing a boolean to `true` is redundant; `if on` already does that (a topic for chapter 4, but the gist is visible). Notice the output format is identical to the compiler's warnings: same anatomy, same suggested-fix machinery, plus a documentation link explaining the lint in depth. Clippy is the same voice with stronger opinions.

While you're learning, Clippy is close to a free tutor: it catches beginner idioms *and explains the better form*, with that documentation link attached to every lint. Running it now and then on your practice programs will teach you real Rust style faster than any list of rules.

## rustfmt: the end of formatting debates

One more bundled tool completes the set. **rustfmt** automatically formats your code (indentation, spacing, line breaks) to the single standard style the Rust community settled on. Run `cargo fmt` and your whole project snaps to it. We'll have more to say in chapter 1 when we cover code formatting; for now, know that the tool exists, everyone uses it, and entire decades-old arguments about where braces belong do not occur in Rust. It's quietly one of the language's best features.

One lesson left in this chapter: editions, the answer to a question that's been sitting unexplained in your `Cargo.toml` since lesson 0.8.

## Sitemap

See the full [sitemap](https://learnrust.net/sitemap.md) for all pages.
