Lint levels

In rustc, lints are divided into four levels:

  • allow
  • warn
  • deny
  • forbidEach lint has a default level (explained in the lint listing later in thischapter), and the compiler has a default warning level. First, let's explainwhat these levels mean, and then we'll talk about configuration.

allow

These lints exist, but by default, do nothing. For example, consider thissource:

  1. #![allow(unused_variables)]
  2. fn main() {
  3. pub fn foo() {}
  4. }

Compiling this file produces no warnings:

  1. $ rustc lib.rs --crate-type=lib
  2. $

But this code violates the missing_docs lint.

These lints exist mostly to be manually turned on via configuration, as we'lltalk about later in this section.

warn

The 'warn' lint level will produce a warning if you violate the lint. For example,this code runs afoul of the unused_variables lint:

  1. #![allow(unused_variables)]
  2. fn main() {
  3. pub fn foo() {
  4.     let x = 5;
  5. }
  6. }

This will produce this warning:

  1. $ rustc lib.rs --crate-type=lib
  2. warning: unused variable: `x`
  3. --> lib.rs:2:9
  4. |
  5. 2 | let x = 5;
  6. | ^
  7. |
  8. = note: `#[warn(unused_variables)]` on by default
  9. = note: to avoid this warning, consider using `_x` instead

deny

A 'deny' lint produces an error if you violate it. For example, this coderuns into the exceeding_bitshifts lint.

  1. fn main() {
  2. 100u8 << 10;
  3. }
  1. $ rustc main.rs
  2. error: bitshift exceeds the type's number of bits
  3. --> main.rs:2:13
  4. |
  5. 2 | 100u8 << 10;
  6. | ^^^^^^^^^^^
  7. |
  8. = note: `#[deny(exceeding_bitshifts)]` on by default

What's the difference between an error from a lint and a regular old error?Lints are configurable via levels, so in a similar way to 'allow' lints,warnings that are 'deny' by default let you allow them. Similarly, you maywish to set up a lint that is warn by default to produce an error instead.This lint level gives you that.

forbid

'forbid' is a special lint level that's stronger than 'deny'. It's the sameas 'deny' in that a lint at this level will produce an error, but unlike the'deny' level, the 'forbid' level can not be overridden to be anything lowerthan an error. However, lint levels may still be capped with —cap-lints(see below) so rustc —cap-lints warn will make lints set to 'forbid' justwarn.

Configuring warning levels

Remember our missing_docs example from the 'allow' lint level?

  1. $ cat lib.rs
  2. pub fn foo() {}
  3. $ rustc lib.rs --crate-type=lib
  4. $

We can configure this lint to operate at a higher level, both withcompiler flags, as well as with an attribute in the source code.

You can also "cap" lints so that the compiler can choose to ignorecertain lint levels. We'll talk about that last.

Via compiler flag

The -A, -W, -D, and -F flags let you turn one or more lintsinto allowed, warning, deny, or forbid levels, like this:

  1. $ rustc lib.rs --crate-type=lib -W missing-docs
  2. warning: missing documentation for crate
  3. --> lib.rs:1:1
  4. |
  5. 1 | pub fn foo() {}
  6. | ^^^^^^^^^^^^
  7. |
  8. = note: requested on the command line with `-W missing-docs`
  9. warning: missing documentation for a function
  10. --> lib.rs:1:1
  11. |
  12. 1 | pub fn foo() {}
  13. | ^^^^^^^^^^^^
  1. $ rustc lib.rs --crate-type=lib -D missing-docs
  2. error: missing documentation for crate
  3. --> lib.rs:1:1
  4. |
  5. 1 | pub fn foo() {}
  6. | ^^^^^^^^^^^^
  7. |
  8. = note: requested on the command line with `-D missing-docs`
  9. error: missing documentation for a function
  10. --> lib.rs:1:1
  11. |
  12. 1 | pub fn foo() {}
  13. | ^^^^^^^^^^^^
  14. error: aborting due to 2 previous errors

You can also pass each flag more than once for changing multiple lints:

  1. $ rustc lib.rs --crate-type=lib -D missing-docs -D unused-variables

And of course, you can mix these four flags together:

  1. $ rustc lib.rs --crate-type=lib -D missing-docs -A unused-variables

Via an attribute

You can also modify the lint level with a crate-wide attribute:

  1. $ cat lib.rs
  2. #![warn(missing_docs)]
  3. pub fn foo() {}
  4. $ rustc lib.rs --crate-type=lib
  5. warning: missing documentation for crate
  6. --> lib.rs:1:1
  7. |
  8. 1 | / #![warn(missing_docs)]
  9. 2 | |
  10. 3 | | pub fn foo() {}
  11. | |_______________^
  12. |
  13. note: lint level defined here
  14. --> lib.rs:1:9
  15. |
  16. 1 | #![warn(missing_docs)]
  17. | ^^^^^^^^^^^^
  18. warning: missing documentation for a function
  19. --> lib.rs:3:1
  20. |
  21. 3 | pub fn foo() {}
  22. | ^^^^^^^^^^^^

All four, warn, allow, deny, and forbid all work this way.

You can also pass in multiple lints per attribute:

  1. #![allow(unused_variables)]
  2. #![warn(missing_docs, unused_variables)]
  3. fn main() {
  4. pub fn foo() {}
  5. }

And use multiple attributes together:

  1. #![allow(unused_variables)]
  2. #![warn(missing_docs)]
  3. #![deny(unused_variables)]
  4. fn main() {
  5. pub fn foo() {}
  6. }

Capping lints

rustc supports a flag, —cap-lints LEVEL that sets the "lint cap level."This is the maximum level for all lints. So for example, if we take ourcode sample from the "deny" lint level above:

  1. fn main() {
  2. 100u8 << 10;
  3. }

And we compile it, capping lints to warn:

  1. $ rustc lib.rs --cap-lints warn
  2. warning: bitshift exceeds the type's number of bits
  3. --> lib.rs:2:5
  4. |
  5. 2 | 100u8 << 10;
  6. | ^^^^^^^^^^^
  7. |
  8. = note: `#[warn(exceeding_bitshifts)]` on by default
  9. warning: this expression will panic at run-time
  10. --> lib.rs:2:5
  11. |
  12. 2 | 100u8 << 10;
  13. | ^^^^^^^^^^^ attempt to shift left with overflow

It now only warns, rather than errors. We can go further and allow all lints:

  1. $ rustc lib.rs --cap-lints allow
  2. $

This feature is used heavily by Cargo; it will pass —cap-lints allow whencompiling your dependencies, so that if they have any warnings, they do notpollute the output of your build.