add a lot of text about lints

This commit is contained in:
steveklabnik 2018-04-06 12:32:16 -04:00
parent 78b076dadb
commit 50b3a3d121
7 changed files with 824 additions and 0 deletions

View file

@ -1 +1,29 @@
# Lint Groups
`rustc` has the concept of a "lint group", where you can toggle several warnings
through one name.
For example, the `nonstandard-style` lint sets `non-camel-case-types`,
`non-snake-case`, and `non-upper-case-globals` all at once. So these are
equivalent:
```bash
$ rustc -D nonstandard-style
$ rustc -D non-camel-case-types -D non-snake-case -D non-upper-case-globals
```
Here's a list of each lint group, and the lints that they are made up of:
| group | description | lints |
|---------------------|---------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| nonstandard-style | Violation of standard naming conventions | non-camel-case-types, non-snake-case, non-upper-case-globals |
| warnings | all lints that would be issuing warnings | all lints that would be issuing warnings |
| edition-2018 | Lints that will be turned into errors in Rust 2018 | tyvar-behind-raw-pointer |
| rust-2018-idioms | Lints to nudge you toward idiomatic features of Rust 2018 | bare-trait-object, unreachable-pub |
| unused | These lints detect things being declared but not used | unused-imports, unused-variables, unused-assignments, dead-code, unused-mut, unreachable-code, unreachable-patterns, unused-must-use, unused-unsafe, path-statements, unused-attributes, unused-macros, unused-allocation, unused-doc-comment, unused-extern-crates, unused-features, unused-parens |
| future-incompatible | Lints that detect code that has future-compatibility problems | private-in-public, pub-use-of-private-extern-crate, patterns-in-fns-without-body, safe-extern-statics, invalid-type-param-default, legacy-directory-ownership, legacy-imports, legacy-constructor-visibility, missing-fragment-specifier, illegal-floating-point-literal-pattern, anonymous-parameters, parenthesized-params-in-types-and-modules, late-bound-lifetime-arguments, safe-packed-borrows, incoherent-fundamental-impls, tyvar-behind-raw-pointer, unstable-name-collision |
Additionally, there's a `bad-style` lint group that's a deprecated alias for `nonstandard-style`.
Finally, you can also see the table above by invoking `rustc -W help`. This will give you the exact values for the specific
compiler you have installed.

View file

@ -1 +1,28 @@
# Lints
In software, a "lint" is a tool used to help improve your source code. The
Rust compiler contains a number of lints, and when it compiles your code, it will
also run the lints. These lints may produce a warning, an error, or nothing at all,
depending on how you've configured things.
Here's a small example:
```rust
$ cat main.rs
fn main() {
let x = 5;
}
> rustc main.rs
warning: unused variable: `x`
--> main.rs:2:9
|
2 | let x = 5;
| ^
|
= note: #[warn(unused_variables)] on by default
= note: to avoid this warning, consider using `_x` instead
```
This is the `unused_variables` lint, and it tells you that you've introduced
a variable that you don't use in your code. That's not *wrong*, so it's not
an error, but it might be a bug, so you get a warning.

View file

@ -1 +1,252 @@
# Lint levels
In `rustc`, lints are divided into four *levels*:
1. allow
2. warn
3. deny
4. forbid
Each lint has a default level (explained in the lint listing later in this
chapter), and the compiler has a default warning level. First, let's explain
what these levels mean, and then we'll talk about configuration.
## allow
These lints exist, but by default, do nothing. For example, consider this
source:
```rust
pub fn foo() {}
```
Compiling this file produces no warnings:
```rust
$ rustc lib.rs --crate-type=lib
$
```
But this code violates the `missing_docs` lint.
These lints exist mostly to be manually turned on via configuration, as we'll
talk 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_variable` lint:
```rust
pub fn foo() {
let x = 5;
}
```
This will produce this warning:
```bash
> rustc lib.rs --crate-type=lib
warning: unused variable: `x`
--> lib.rs:2:9
|
2 | let x = 5;
| ^
|
= note: #[warn(unused_variables)] on by default
= note: to avoid this warning, consider using `_x` instead
```
## deny
A 'deny' lint produces an error if you violate it. For example, this code
runs into the `exceeding_bitshifts` lint.
```rust
fn main() {
100u8 << 10;
}
```
```bash
> rustc main.rs
error: bitshift exceeds the type's number of bits
--> main.rs:2:13
|
2 | 100u8 << 10;
| ^^^^^^^^^^^
|
= 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 may
wish 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 same
as '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 lower
than an error.
## Configuring warning levels
Remember our `missing_docs` example from the 'allow' lint level?
```bash
$ cat lib.rs
pub fn foo() {}
$ rustc lib.rs --crate-type=lib
$
```
We can configure this lint to operate at a higher level, both with
compiler flags, as well as with an attribute in the source code.
You can also "cap" lints so that the compiler can choose to ignore
certain lint levels. We'll talk about that last.
### Via compiler flag
The `-A`, `-W`, `-D`, and `-F` flags let you turn one or more lints
into allowed, warning, deny, or forbid levels, like this:
```bash
$ rustc lib.rs --crate-type=lib -W missing-docs
warning: missing documentation for crate
--> lib.rs:1:1
|
1 | pub fn foo() {}
| ^^^^^^^^^^^^
|
= note: requested on the command line with `-W missing-docs`
warning: missing documentation for a function
--> lib.rs:1:1
|
1 | pub fn foo() {}
| ^^^^^^^^^^^^
> rustc lib.rs --crate-type=lib -D missing-docs
error: missing documentation for crate
--> lib.rs:1:1
|
1 | pub fn foo() {}
| ^^^^^^^^^^^^
|
= note: requested on the command line with `-D missing-docs`
error: missing documentation for a function
--> lib.rs:1:1
|
1 | pub fn foo() {}
| ^^^^^^^^^^^^
error: aborting due to 2 previous errors
```
You can also pass each flag more than once for changing multiple lints:
```bash
rustc lib.rs --crate-type=lib -D missing-docs -D unused-variables
```
And of course, you can mix these four flags together:
```bash
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:
```bash
> cat lib.rs
#![warn(missing_docs)]
pub fn foo() {}
$ rustc lib.rs --crate-type=lib
warning: missing documentation for crate
--> lib.rs:1:1
|
1 | / #![warn(missing_docs)]
2 | |
3 | | pub fn foo() {}
| |_______________^
|
note: lint level defined here
--> lib.rs:1:9
|
1 | #![warn(missing_docs)]
| ^^^^^^^^^^^^
warning: missing documentation for a function
--> lib.rs:3:1
|
3 | pub fn foo() {}
| ^^^^^^^^^^^^
```
All four, `warn`, `allow`, `deny`, and `forbid` all work this way.
You can also pass in multiple lints per attribute:
```rust
#![warn(missing_docs, unused_variables)]
pub fn foo() {}
```
And use multiple attributes together:
```rust
#![warn(missing_docs)]
#![deny(unused_variables)]
pub fn foo() {}
```
### 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 our
code sample from the "deny" lint level above:
```rust
fn main() {
100u8 << 10;
}
```
And we compile it, capping lints to warn:
```bash
$ rustc lib.rs --cap-lints warn
warning: bitshift exceeds the type's number of bits
--> lib.rs:2:5
|
2 | 100u8 << 10;
| ^^^^^^^^^^^
|
= note: #[warn(exceeding_bitshifts)] on by default
warning: this expression will panic at run-time
--> lib.rs:2:5
|
2 | 100u8 << 10;
| ^^^^^^^^^^^ attempt to shift left with overflow
```
It now only warns, rather than errors. We can go further and allow all lints:
```bash
$ rustc lib.rs --cap-lints allow
$
```
This feature is used heavily by Cargo; it will pass `--cap-lints allow` when
compiling your dependencies, so that if they have any warnings, they do not
pollute the output of your build.

View file

@ -1 +1,452 @@
# Allowed-by-default lints
These lints are all set to the 'allow' level by default. As such, they won't show up
unless you set them to a higher lint level with a flag or attribute.
## anonymous-parameters
This lint detects anonymous parameters. Some example code that triggers this lint:
```rust
trait Foo {
fn foo(usize);
}
```
When set to 'deny', this will produce:
```text
error: use of deprecated anonymous parameter
--> src/lib.rs:5:11
|
5 | fn foo(usize);
| ^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686>
```
This syntax is mostly a historical accident, and can be worked around quite
easily:
```rust
trait Foo {
fn foo(_: usize);
}
```
## bare-trait-object
This lint suggests using `dyn Trait` for trait objects. Some example code
that triggers this lint:
```rust
#![feature(dyn_trait)]
trait Trait { }
fn takes_trait_object(_: Box<Trait>) {
}
```
When set to 'deny', this will produce:
```text
error: trait objects without an explicit `dyn` are deprecated
--> src/lib.rs:7:30
|
7 | fn takes_trait_object(_: Box<Trait>) {
| ^^^^^ help: use `dyn`: `dyn Trait`
|
```
To fix it, do as the help message suggests:
```rust
#![feature(dyn_trait)]
#![deny(bare_trait_object)]
trait Trait { }
fn takes_trait_object(_: Box<dyn Trait>) {
}
```
## box-pointers
This lints use of the Box type. Some example code that triggers this lint:
```rust
struct Foo {
x: Box<isize>,
}
```
When set to 'deny', this will produce:
```text
error: type uses owned (Box type) pointers: std::boxed::Box<isize>
--> src/lib.rs:6:5
|
6 | x: Box<isize> //~ ERROR type uses owned
| ^^^^^^^^^^^^^
|
```
This lint is mostly historical, and not particularly useful. `Box<T>` used to
be built into the language, and the only way to do heap allocation. Today's
Rust can call into other allocators, etc.
## elided-lifetime-in-path
This lint detects the use of hidden lifetime parameters. Some example code
that triggers this lint:
```rust
struct Foo<'a> {
x: &'a u32
}
fn foo(x: &Foo) {
}
```
When set to 'deny', this will produce:
```text
error: hidden lifetime parameters are deprecated, try `Foo<'_>`
--> src/lib.rs:5:12
|
5 | fn foo(x: &Foo) {
| ^^^
|
```
Lifetime elision elides this lifetime, but that is being deprecated.
## missing-copy-implementations
This lint detects potentially-forgotten implementations of `Copy`. Some
example code that triggers this lint:
```rust
pub struct Foo {
pub field: i32
}
```
When set to 'deny', this will produce:
```text
error: type could implement `Copy`; consider adding `impl Copy`
--> src/main.rs:3:1
|
3 | / pub struct Foo { //~ ERROR type could implement `Copy`; consider adding `impl Copy`
4 | | pub field: i32
5 | | }
| |_^
|
```
You can fix the lint by deriving `Copy`.
This lint is set to 'allow' because this code isn't bad; it's common to write
newtypes like this specifically so that a `Copy` type is no longer `Copy`.
## missing-debug-implementations
This lint detects missing implementations of `fmt::Debug`. Some example code
that triggers this lint:
```rust
pub struct Foo;
```
When set to 'deny', this will produce:
```text
error: type does not implement `fmt::Debug`; consider adding #[derive(Debug)] or a manual implementation
--> src/main.rs:3:1
|
3 | pub struct Foo;
| ^^^^^^^^^^^^^^^
|
```
You can fix the lint by deriving `Debug`.
## missing-docs
This lint detects missing documentation for public items. Some example code
that triggers this lint:
```rust
pub fn foo() {}
```
When set to 'deny', this will produce:
```text
error: missing documentation for crate
--> src/main.rs:1:1
|
1 | / #![deny(missing_docs)]
2 | |
3 | | pub fn foo() {}
4 | |
5 | | fn main() {}
| |____________^
|
error: missing documentation for a function
--> src/main.rs:3:1
|
3 | pub fn foo() {}
| ^^^^^^^^^^^^
```
To fix the lint, add documentation to all items.
## single-use-lifetime
This lint detects lifetimes that are only used once. Some example code that
triggers this lint:
```rust
struct Foo<'x> {
x: &'x u32
}
```
When set to 'deny', this will produce:
```text
error: lifetime name `'x` only used once
--> src/main.rs:3:12
|
3 | struct Foo<'x> {
| ^^
|
```
## trivial-casts
This lint detects trivial casts which could be removed. Some example code
that triggers this lint:
```rust
let x: &u32 = &42;
let _ = x as *const u32;
```
When set to 'deny', this will produce:
```text
error: trivial cast: `&u32` as `*const u32`. Cast can be replaced by coercion, this might require type ascription or a temporary variable
--> src/main.rs:5:13
|
5 | let _ = x as *const u32;
| ^^^^^^^^^^^^^^^
|
note: lint level defined here
--> src/main.rs:1:9
|
1 | #![deny(trivial_casts)]
| ^^^^^^^^^^^^^
```
## trivial-numeric-casts
This lint detects trivial casts of numeric types which could be removed. Some
example code that triggers this lint:
```rust
let x = 42i32 as i32;
```
When set to 'deny', this will produce:
```text
error: trivial numeric cast: `i32` as `i32`. Cast can be replaced by coercion, this might require type ascription or a temporary variable
--> src/main.rs:4:13
|
4 | let x = 42i32 as i32;
| ^^^^^^^^^^^^
|
```
## unreachable-pub
This lint triggers for `pub` items not reachable from the crate root. Some
example code that triggers this lint:
```rust
mod foo {
pub mod bar {
}
}
```
When set to 'deny', this will produce:
```text
error: unreachable `pub` item
--> src/main.rs:4:5
|
4 | pub mod bar {
| ---^^^^^^^^
| |
| help: consider restricting its visibility: `pub(crate)`
|
```
## unsafe-code
This lint catches usage of `unsafe` code. Some example code that triggers this lint:
```rust
fn main() {
unsafe {
}
}
```
When set to 'deny', this will produce:
```text
error: usage of an `unsafe` block
--> src/main.rs:4:5
|
4 | / unsafe {
5 | |
6 | | }
| |_____^
|
```
## unstable-features
This lint is deprecated and no longer used.
## unused-extern-crates
This lint guards against `extern crate` items that are never used. Some
example code that triggers this lint:
```rust
extern crate semver;
```
When set to 'deny', this will produce:
```text
error: unused extern crate
--> src/main.rs:3:1
|
3 | extern crate semver;
| ^^^^^^^^^^^^^^^^^^^^
|
```
## unused-import-braces
This lint catches unnecessary braces around an imported item. Some example
code that triggers this lint:
```rust
use test::{A};
mod test {
struct A;
}
```
When set to 'deny', this will produce:
```text
error: braces around A is unnecessary
--> src/main.rs:3:1
|
3 | use test::{A};
| ^^^^^^^^^^^^^^
|
```
To fix it, `use test::A;`
## unused-qualifications
This lint detects unnecessarily qualified names. Some example code that triggers this lint:
```rust
mod foo {
pub fn bar() {}
}
fn main() {
use foo::bar;
foo::bar();
}
```
When set to 'deny', this will produce:
```text
error: unnecessary qualification
--> src/main.rs:9:5
|
9 | foo::bar();
| ^^^^^^^^
|
```
You can call `bar()` directly, without the `foo::`.
## unused-results
This lint checks for the unused result of an expression in a statement. Some
example code that triggers this lint:
```rust
fn foo<T>() -> T { panic!() }
fn main() {
foo::<usize>();
}
```
When set to 'deny', this will produce:
```text
error: unused result
--> src/main.rs:6:5
|
6 | foo::<usize>();
| ^^^^^^^^^^^^^^^
|
```
## variant-size-differences
This lint detects enums with widely varying variant sizes. Some example code that triggers this lint:
```rust
enum En {
V0(u8),
VBig([u8; 1024]), //~ ERROR variant is more than three times larger
}
```
When set to 'deny', this will produce:
```text
error: enum variant is more than three times larger (1024 bytes) than the next largest
--> src/main.rs:5:5
|
5 | VBig([u8; 1024]), //~ ERROR variant is more than three times larger
| ^^^^^^^^^^^^^^^^
|
```

View file

@ -1 +1,16 @@
# Deny-by-default lints
These lints are all set to the 'deny' level by default.
exceeding-bitshifts deny shift exceeds the type's number of bits
invalid-type-param-default deny type parameter default erroneously allowed in invalid location
legacy-constructor-visibility deny detects use of struct constructors that would be invisible with new visibility rules
legacy-directory-ownership deny non-inline, non-`#[path]` modules (e.g. `mod foo;`) were erroneously allowed in some files not named `mod.rs`
legacy-imports deny detects names that resolve to ambiguous glob imports with RFC 1560
missing-fragment-specifier deny detects missing fragment specifiers in unused `macro_rules!` patterns
mutable-transmutes deny mutating transmuted &mut T from &T may cause undefined behavior
no-mangle-const-items deny const items will not have their symbols exported
parenthesized-params-in-types-and-modules deny detects parenthesized generic parameters in type and module names
pub-use-of-private-extern-crate deny detect public re-exports of private extern crates
safe-extern-statics deny safe access to extern statics was erroneously allowed
unknown-crate-types deny unknown crate type found in #[crate_type] directive

View file

@ -1 +1,5 @@
# Lint listing
This section lists out all of the lints, grouped by their default lint levels.
You can also see this list by running `rustc -W help`.

View file

@ -1 +1,49 @@
# Warn-by-default lints
These lints are all set to the 'warn' level by default.
const-err warn constant evaluation detected erroneous expression
dead-code warn detect unused, unexported items
deprecated warn detects use of deprecated items
illegal-floating-point-literal-pattern warn floating-point literals cannot be used in patterns
improper-ctypes warn proper use of libc types in foreign modules
incoherent-fundamental-impls warn potentially-conflicting impls were erroneously allowed
late-bound-lifetime-arguments warn detects generic lifetime arguments in path segments with late bound lifetime parameters
non-camel-case-types warn types, variants, traits and type parameters should have camel case names
non-shorthand-field-patterns warn using `Struct { x: x }` instead of `Struct { x }` in a pattern
non-snake-case warn variables, methods, functions, lifetime parameters and modules should have snake case names
non-upper-case-globals warn static constants should have uppercase identifiers
no-mangle-generic-items warn generic items must be mangled
overflowing-literals warn literal out of range for its type
path-statements warn path statements with no effect
patterns-in-fns-without-body warn patterns in functions without body were erroneously allowed
plugin-as-library warn compiler plugin used as ordinary library in non-plugin crate
private-in-public warn detect private items in public interfaces not caught by the old implementation
private-no-mangle-fns warn functions marked #[no_mangle] should be exported
private-no-mangle-statics warn statics marked #[no_mangle] should be exported
renamed-and-removed-lints warn lints that have been renamed or removed
safe-packed-borrows warn safe borrows of fields of packed structs were was erroneously allowed
stable-features warn stable features found in #[feature] directive
type-alias-bounds warn bounds in type aliases are not enforced
tyvar-behind-raw-pointer warn raw pointer to an inference variable
unconditional-recursion warn functions that cannot return without calling themselves
unions-with-drop-fields warn use of unions that contain fields with possibly non-trivial drop code
unknown-lints warn unrecognized lint attribute
unreachable-code warn detects unreachable code paths
unreachable-patterns warn detects unreachable patterns
unstable-name-collision warn detects name collision with an existing but unstable method
unused-allocation warn detects unnecessary allocations that can be eliminated
unused-assignments warn detect assignments that will never be read
unused-attributes warn detects attributes that were not used by the compiler
unused-comparisons warn comparisons made useless by limits of the types involved
unused-doc-comment warn detects doc comments that aren't used by rustdoc
unused-features warn unused or unknown features found in crate-level #[feature] directives
unused-imports warn imports that are never used
unused-macros warn detects macros that were not used
unused-must-use warn unused result of a type flagged as #[must_use]
unused-mut warn detect mut variables which don't need to be mutable
unused-parens warn `if`, `match`, `while` and `return` do not need parentheses
unused-unsafe warn unnecessary use of an `unsafe` block
unused-variables warn detect variables which are not used in any way
warnings warn mass-change the level for lints which produce warnings
while-true warn suggest using `loop { }` instead of `while true { }`