Skip to Content
Course content

75: Linting with Clippy

Click on the "Edit" button in the top corner of the screen to edit your slide content.

Wait, isn't the compiler already telling me everything I need to fix?

In a way, yes. The Rust compiler is incredibly strict—it won't even let you run the code if you've got a borrow checker violation. But there's a big difference between code that is valid and code that is idiomatic. Clippy is a collection of lints that look for "smells." It's less like a compiler and more like a senior engineer doing a code review on your PR.

For example, the compiler doesn't care if you write a manual loop to check if a vector is empty, but Clippy will nudge you toward a cleaner solution. I've seen countless beginners do this:

if my_vec.len() == 0 {
    println!("It's empty!");
}

The compiler says "this is fine." Clippy says "Why not just use my_vec.is_empty()? It's more readable and often more intent-revealing."

How do I actually run this thing, and what am I looking at?

You don't need to install anything separate if you have Rustup. Just run cargo clippy in your terminal. It plugs right into the Cargo workflow, so it sees all your dependencies and crate configurations.

When it runs, you'll see warnings categorized by "lint groups." You'll see things like style, complexity, and perf. I always pay the most attention to correctness and perf first. If Clippy tells you that a certain pattern is likely a bug (correctness) or that you're allocating memory unnecessarily (perf), you should probably fix it immediately. Style lints are great for making your code look like it was written by a seasoned Rustacean, but they aren't "breaking" anything.

What if Clippy is just plain wrong (or too annoying)?

It happens. Sometimes you have a very specific reason for doing something the "wrong" way—maybe you're interfacing with a weird C API or you're optimizing a hot loop in a way that Clippy doesn't recognize. You don't have to rewrite your logic just to please the tool.

You can silence a specific lint using attributes. If you put #[allow(clippy::lint_name)] above a function or a block of code, Clippy will ignore that specific rule for that section. I usually do this sparingly, though. If you find yourself adding #[allow] everywhere, it's a sign you might be fighting the language rather than working with it.

#[allow(clippy::too_many_arguments)]
fn process_complex_transaction(a: i32, b: i32, c: i32, d: i32, e: i32, f: i32) {
    // I know this function has too many arguments, 
    // but it's mirroring a legacy database schema.
}

Can I make Clippy even stricter?

If you're a completionist (or working on a production system where you want zero ambiguity), you can enable "pedantic" lints. By default, Clippy only shows you the most common, high-impact suggestions. To go deeper, you can add this to the top of your main.rs or lib.rs:

#![warn(clippy::pedantic)]

Fair warning: this will likely flood your terminal with warnings. It'll complain about things like missing documentation on public items or using unwrap() where a more explicit error handle would be better. I recommend turning this on only after you've cleaned up the standard warnings.




📋 Practical Task

Refactoring the Inventory Manager

You have been handed a small piece of code for an inventory management system. While it compiles and runs perfectly, it is written in a very "non-Rust" way. Your goal is to run cargo clippy on this code and apply the suggested fixes to make it idiomatic.

The Code:

fn main() {
    let inventory = vec!["Apple", "Banana", "Cherry"];
    let mut found = false;

    // Task: Clippy will suggest a more idiomatic way to check if 
    // an element exists in a slice/vec than a manual for loop.
    for item in inventory.iter() {
        if *item == "Banana" {
            found = true;
            break;
        }
    }

    if found == true {
        println!("Banana is in stock!");
    }

    // Task: Clippy will notice you are cloning a String 
    // that is immediately dropped, or using an inefficient 
    // way to create a string.
    let greeting = String::from("Inventory Check") + " Completed";
    println!("{}", greeting);
}

Instructions:

  1. Create a new Rust project and paste the code above into main.rs.
  2. Run cargo clippy in your terminal.
  3. Read the suggestions provided by the linter.
  4. Modify the code to replace the for loop with a built-in method (like .contains()) and clean up the boolean comparison (found == true).
  5. Fix the string concatenation to use the format! macro or a more efficient alternative as suggested.
  6. Run cargo clippy again to ensure all warnings are gone.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.