Skip to content

/flags/rust/rustc-d-warnings

rustc -D warnings (RUSTFLAGS="-D warnings"): treat warnings as errors

verified onenvironmentlocal · windows 10.0.26200 arm64 · GNU bash 5.3.15 (Git Bash) · rustc 1.98.1 (48a229cea 2026-09-01)updated
tool
Rust
command
rustc
flag
-D warnings (--deny warnings)
default
most lints are warn: warnings are printed and the build succeeds

rustc -D warnings main.rs raises every lint that is currently a warning to an error, so the build fails instead of printing warning: ... emitted and succeeding. In Cargo projects it is usually passed as RUSTFLAGS="-D warnings" cargo build or cargo clippy -- -D warnings, typically in CI. -D is short for --deny; the other lint levels are -A (allow), -W (warn), --force-warn and -F (forbid).

Without and with -D warnings

bash
cat > w.rs <<'EOF'
fn main() {
    let unused = 5;
    let mut n = 1;
    println!("{}", 2);
}
EOF
echo "== default"
rustc w.rs 2>&1 | grep -E "^(warning: unused|warning: variable|warning: [0-9])"; echo "exit: ${PIPESTATUS[0]}"
echo "== -D warnings"
rustc -D warnings w.rs 2>&1 | sed -n '1,9p'; echo "exit: ${PIPESTATUS[0]}"
echo "== -D warnings -A unused-mut -A unused-variables"
rustc -D warnings -A unused-mut -A unused-variables w.rs; echo "exit: $?"
echo "== -A before -D warnings"
rustc -A unused-mut -A unused-variables -D warnings w.rs; echo "exit: $?"

Output

== default
warning: variable does not need to be mutable
warning: unused variable: `unused`
warning: unused variable: `n`
warning: 3 warnings emitted
exit: 0
== -D warnings
error: variable does not need to be mutable
 --> w.rs:3:9
  |
3 |     let mut n = 1;
  |         ----^
  |         |
  |         help: remove this `mut`
  |
  = note: `-D unused-mut` implied by `-D warnings`
exit: 1
== -D warnings -A unused-mut -A unused-variables
exit: 0
== -A before -D warnings
exit: 0

By default rustc prints three warnings and builds the binary (exit 0). With -D warnings the same messages become errors, each with a note saying which lint was denied and how to override it, and the build stops with exit code 1. Allowing specific lints with -A exempts them, whether the -A comes before or after -D warnings: the warnings group only affects lints that would otherwise be reported as warnings.

Lint level flags

FlagLong formEffect
-A lint--allowDo not report the lint
-W lint--warnReport as a warning
--force-warn lintReport as a warning, even if the code says #[allow]
-D lint--denyReport as an error; code may still #[allow] it
-F lint--forbidReport as an error that the code cannot override
--cap-lints LEVELUpper limit for every lint; Cargo uses --cap-lints allow for dependencies

warnings is a special group meaning "everything that would be a warning". You can also name a group such as unused or rust-2018-idioms, or a single lint such as unused-variables (dashes and underscores are equivalent).

In Cargo projects

bash
RUSTFLAGS="-D warnings" cargo build            # rustc lints for the whole workspace
cargo clippy --all-targets -- -D warnings      # clippy lints as errors too
RUSTDOCFLAGS="-D warnings" cargo doc --no-deps # broken intra-doc links fail the docs build

Since Rust 1.74 a [lints] table in Cargo.toml sets levels per crate without touching RUSTFLAGS:

Cargo.toml
[lints.rust]
unsafe_code = "forbid"
unused = "deny"

[lints.clippy]
unwrap_used = "warn"

Pitfalls

  • New compilers add warnings. A pinned -D warnings in CI can turn a toolchain update into a red build. Pin the toolchain with rust-toolchain.toml or treat those failures as routine maintenance.
  • Allowed lints stay allowed: -D warnings does not re-enable lints switched off with -A or #[allow]. To make a specific lint an error regardless, name it: -D unused-mut.
  • Only lints are affected. Hard errors such as E0382 borrow of moved value are errors at every level; -D warnings cannot make them warnings and -A cannot hide them. Use rustc --explain for the error codes.

FAQ

Why does RUSTFLAGS="-D warnings" rebuild all dependencies?

RUSTFLAGS is part of the build fingerprint, so changing it invalidates every cached artifact, dependencies included. Warnings in dependencies are capped by Cargo and do not fail the build, but the rebuild still costs time. Keep the same RUSTFLAGS in every CI step, or use the [lints] table, which applies only to your own crates.

How do I allow one lint while denying all warnings?

Add -A lint-name, for example rustc -D warnings -A unused-mut, or put #[allow(unused_mut)] on the item. The example on this page shows that the allowed lint stays allowed whichever order the flags have.

Is -D warnings the same as #![deny(warnings)] in the code?

It has the same effect, but the attribute is part of the source and breaks the build for everyone who compiles the crate with a newer compiler that adds warnings. Prefer the command-line flag in CI.

Sources