diff --git a/rust-1.46.0/index.html b/rust-1.46.0/index.html new file mode 100644 index 000000000..e11f2eeba --- /dev/null +++ b/rust-1.46.0/index.html @@ -0,0 +1,277 @@ + + + + + + + ALL the Clippy Lints + + + + + + +
+ + + + +
+ + + + +
+
+
+
+

Lint levels

+
+ +
+
+
+
+
+

Lint groups

+
+ +
+
+
+
+
+
+
+ + + + + +
+
+
+
+ +
+
+

+
+ {{lint.id}} + +
+ +
+ {{lint.group}} + + Allow + Warn + Deny + Deprecated + + +
+

+
+ +
    +
  • +

    + {{title}} +

    +
    +
  • +
+
+
+
+ + + Fork me on Github + + + + + + + + + diff --git a/rust-1.46.0/lints.json b/rust-1.46.0/lints.json new file mode 100644 index 000000000..83a736cf7 --- /dev/null +++ b/rust-1.46.0/lints.json @@ -0,0 +1,4280 @@ +[ + { + "id": "absurd_extreme_comparisons", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for comparisons where one side of the relation is\neither the minimum or maximum value for its type and warns if it involves a\ncase that is always true or always false. Only integer and boolean types are\nchecked.", + "Why is this bad": "An expression like `min <= x` may misleadingly imply\nthat it is possible for `x` to be less than the minimum. Expressions like\n`max < x` are probably mistakes.", + "Known problems": "For `usize` the size of the current compile target will\nbe assumed (e.g., 64 bits on 64 bit systems). This means code that uses such\na comparison to detect target pointer width will trigger this lint. One can\nuse `mem::sizeof` and compare its value or conditional compilation\nattributes\nlike `#[cfg(target_pointer_width = \"64\")] ..` instead.", + "Example": "```rust\nlet vec: Vec = Vec::new();\nif vec.len() <= 0 {}\nif 100 > i32::MAX {}\n```" + } + }, + { + "id": "almost_swapped", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for `foo = bar; bar = foo` sequences.", + "Why is this bad": "This looks like a failed attempt to swap.", + "Known problems": "None.", + "Example": "```rust\na = b;\nb = a;\n```\nIf swapping is intended, use `swap()` instead:\n```rust\nstd::mem::swap(&mut a, &mut b);\n```" + } + }, + { + "id": "approx_constant", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for floating point literals that approximate\nconstants which are defined in\n[`std::f32::consts`](https://doc.rust-lang.org/stable/std/f32/consts/#constants)\nor\n[`std::f64::consts`](https://doc.rust-lang.org/stable/std/f64/consts/#constants),\nrespectively, suggesting to use the predefined constant.", + "Why is this bad": "Usually, the definition in the standard library is more\nprecise than what people come up with. If you find that your definition is\nactually more precise, please [file a Rust\nissue](https://github.com/rust-lang/rust/issues).", + "Known problems": "None.", + "Example": "```rust\nlet x = 3.14;\nlet y = 1_f64 / x;\n```\nUse predefined constants instead:\n```rust\nlet x = std::f32::consts::PI;\nlet y = std::f64::consts::FRAC_1_PI;\n```" + } + }, + { + "id": "as_conversions", + "group": "restriction", + "level": "Allow", + "docs": { + "What it does": "Checks for usage of `as` conversions.", + "Why is this bad": "`as` conversions will perform many kinds of\nconversions, including silently lossy conversions and dangerous coercions.\nThere are cases when it makes sense to use `as`, so the lint is\nAllow by default.", + "Known problems": "None.", + "Example": "```rust,ignore\nlet a: u32;\n...\nf(a as u16);\n```\n\nUsually better represents the semantics you expect:\n```rust,ignore\nf(a.try_into()?);\n```\nor\n```rust,ignore\nf(a.try_into().expect(\"Unexpected u16 overflow in f\"));\n```" + } + }, + { + "id": "assertions_on_constants", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for `assert!(true)` and `assert!(false)` calls.", + "Why is this bad": "Will be optimized out by the compiler or should probably be replaced by a\n`panic!()` or `unreachable!()`", + "Known problems": "None", + "Example": "```rust,ignore\nassert!(false)\nassert!(true)\nconst B: bool = false;\nassert!(B)\n```" + } + }, + { + "id": "assign_op_pattern", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for `a = a op b` or `a = b commutative_op a`\npatterns.", + "Why is this bad": "These can be written as the shorter `a op= b`.", + "Known problems": "While forbidden by the spec, `OpAssign` traits may have\nimplementations that differ from the regular `Op` impl.", + "Example": "```rust\nlet mut a = 5;\nlet b = 0;\n// ...\n// Bad\na = a + b;\n\n// Good\na += b;\n```" + } + }, + { + "id": "assign_ops", + "group": "deprecated", + "level": "Deprecated", + "docs": { + "What it does": "Nothing. This lint has been deprecated.", + "Deprecation reason": "This lint is too subjective, not having a good reason for being in clippy.\nAdditionally, compound assignment operators may be overloaded separately from their non-assigning\ncounterparts, so this lint may suggest a change in behavior or the code may not compile." + } + }, + { + "id": "await_holding_lock", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for calls to await while holding a\nnon-async-aware MutexGuard.", + "Why is this bad": "The Mutex types found in syd::sync and parking_lot\nare not designed to operator in an async context across await points.\n\nThere are two potential solutions. One is to use an asynx-aware Mutex\ntype. Many asynchronous foundation crates provide such a Mutex type. The\nother solution is to ensure the mutex is unlocked before calling await,\neither by introducing a scope or an explicit call to Drop::drop.", + "Known problems": "None.", + "Example": "```rust,ignore\nuse std::sync::Mutex;\n\nasync fn foo(x: &Mutex) {\n let guard = x.lock().unwrap();\n *guard += 1;\n bar.await;\n}\n```\n\nUse instead:\n```rust,ignore\nuse std::sync::Mutex;\n\nasync fn foo(x: &Mutex) {\n {\n let guard = x.lock().unwrap();\n *guard += 1;\n }\n bar.await;\n}\n```" + } + }, + { + "id": "bad_bit_mask", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for incompatible bit masks in comparisons.\n\nThe formula for detecting if an expression of the type `_ m\n c` (where `` is one of {`&`, `|`} and `` is one of\n{`!=`, `>=`, `>`, `!=`, `>=`, `>`}) can be determined from the following\ntable:\n\n|Comparison |Bit Op|Example |is always|Formula |\n|------------|------|------------|---------|----------------------|\n|`==` or `!=`| `&` |`x & 2 == 3`|`false` |`c & m != c` |\n|`<` or `>=`| `&` |`x & 2 < 3` |`true` |`m < c` |\n|`>` or `<=`| `&` |`x & 1 > 1` |`false` |`m <= c` |\n|`==` or `!=`| `|` |`x | 1 == 0`|`false` |`c | m != c` |\n|`<` or `>=`| `|` |`x | 1 < 1` |`false` |`m >= c` |\n|`<=` or `>` | `|` |`x | 1 > 0` |`true` |`m > c` |", + "Why is this bad": "If the bits that the comparison cares about are always\nset to zero or one by the bit mask, the comparison is constant `true` or\n`false` (depending on mask, compared value, and operators).\n\nSo the code is actively misleading, and the only reason someone would write\nthis intentionally is to win an underhanded Rust contest or create a\ntest-case for this lint.", + "Known problems": "None.", + "Example": "```rust\nif (x & 1 == 2) { }\n```" + } + }, + { + "id": "bind_instead_of_map", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for usage of `_.and_then(|x| Some(y))`, `_.and_then(|x| Ok(y))` or\n`_.or_else(|x| Err(y))`.", + "Why is this bad": "Readability, this can be written more concisely as\n`_.map(|x| y)` or `_.map_err(|x| y)`.", + "Known problems": "None", + "Example": "```rust\nlet _ = opt().and_then(|s| Some(s.len()));\nlet _ = res().and_then(|s| if s.len() == 42 { Ok(10) } else { Ok(20) });\nlet _ = res().or_else(|s| if s.len() == 42 { Err(10) } else { Err(20) });\n```\n\nThe correct use would be:\n\n```rust\nlet _ = opt().map(|s| s.len());\nlet _ = res().map(|s| if s.len() == 42 { 10 } else { 20 });\nlet _ = res().map_err(|s| if s.len() == 42 { 10 } else { 20 });\n```" + } + }, + { + "id": "blacklisted_name", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for usage of blacklisted names for variables, such\nas `foo`.", + "Why is this bad": "These names are usually placeholder names and should be\navoided.", + "Known problems": "None.", + "Example": "```rust\nlet foo = 3.14;\n```", + "Configuration": "This lint has the following configuration variables:\n\n* `blacklisted-names: Vec`: The list of blacklisted names to lint about. NB: `bar` is not here since it has legitimate uses (defaults to `[\"foo\", \"baz\", \"quux\"]`)." + } + }, + { + "id": "blocks_in_if_conditions", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for `if` conditions that use blocks containing an\nexpression, statements or conditions that use closures with blocks.", + "Why is this bad": "Style, using blocks in the condition makes it hard to read.", + "Known problems": "None.", + "Examples": "```rust\n// Bad\nif { true } { /* ... */ }\n\n// Good\nif true { /* ... */ }\n```\n\n// or\n\n```rust\n\n// Bad\nif { let x = somefunc(); x } { /* ... */ }\n\n// Good\nlet res = { let x = somefunc(); x };\nif res { /* ... */ }\n```" + } + }, + { + "id": "bool_comparison", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for expressions of the form `x == true`,\n`x != true` and order comparisons such as `x < true` (or vice versa) and\nsuggest using the variable directly.", + "Why is this bad": "Unnecessary code.", + "Known problems": "None.", + "Example": "```rust,ignore\nif x == true {}\nif y == false {}\n```\nuse `x` directly:\n```rust,ignore\nif x {}\nif !y {}\n```" + } + }, + { + "id": "borrow_interior_mutable_const", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks if `const` items which is interior mutable (e.g.,\ncontains a `Cell`, `Mutex`, `AtomicXxxx`, etc.) has been borrowed directly.", + "Why is this bad": "Consts are copied everywhere they are referenced, i.e.,\nevery time you refer to the const a fresh instance of the `Cell` or `Mutex`\nor `AtomicXxxx` will be created, which defeats the whole purpose of using\nthese types in the first place.\n\nThe `const` value should be stored inside a `static` item.", + "Known problems": "None", + "Example": "```rust\nuse std::sync::atomic::{AtomicUsize, Ordering::SeqCst};\nconst CONST_ATOM: AtomicUsize = AtomicUsize::new(12);\n\n// Bad.\nCONST_ATOM.store(6, SeqCst); // the content of the atomic is unchanged\nassert_eq!(CONST_ATOM.load(SeqCst), 12); // because the CONST_ATOM in these lines are distinct\n\n// Good.\nstatic STATIC_ATOM: AtomicUsize = CONST_ATOM;\nSTATIC_ATOM.store(9, SeqCst);\nassert_eq!(STATIC_ATOM.load(SeqCst), 9); // use a `static` item to refer to the same instance\n```" + } + }, + { + "id": "borrowed_box", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for use of `&Box` anywhere in the code.", + "Why is this bad": "Any `&Box` can also be a `&T`, which is more\ngeneral.", + "Known problems": "None.", + "Example": "```rust,ignore\nfn foo(bar: &Box) { ... }\n```\n\nBetter:\n\n```rust,ignore\nfn foo(bar: &T) { ... }\n```" + } + }, + { + "id": "box_vec", + "group": "perf", + "level": "Warn", + "docs": { + "What it does": "Checks for use of `Box>` anywhere in the code.", + "Why is this bad": "`Vec` already keeps its contents in a separate area on\nthe heap. So if you `Box` it, you just add another level of indirection\nwithout any benefit whatsoever.", + "Known problems": "None.", + "Example": "```rust,ignore\nstruct X {\n values: Box>,\n}\n```\n\nBetter:\n\n```rust,ignore\nstruct X {\n values: Vec,\n}\n```" + } + }, + { + "id": "boxed_local", + "group": "perf", + "level": "Warn", + "docs": { + "What it does": "Checks for usage of `Box` where an unboxed `T` would\nwork fine.", + "Why is this bad": "This is an unnecessary allocation, and bad for\nperformance. It is only necessary to allocate if you wish to move the box\ninto something.", + "Known problems": "None.", + "Example": "```rust\n\n// Bad\nlet x = Box::new(1);\nfoo(*x);\nprintln!(\"{}\", *x);\n\n// Good\nlet x = 1;\nfoo(x);\nprintln!(\"{}\", x);\n```", + "Configuration": "This lint has the following configuration variables:\n\n* `too-large-for-stack: u64`: The maximum size of objects (in bytes) that will be linted. Larger objects are ok on the heap (defaults to `200`)." + } + }, + { + "id": "builtin_type_shadow", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Warns if a generic shadows a built-in type.", + "Why is this bad": "This gives surprising type errors.", + "Known problems": "None.", + "Example": "```ignore\nimpl Foo {\n fn impl_func(&self) -> u32 {\n 42\n }\n}\n```" + } + }, + { + "id": "cargo_common_metadata", + "group": "cargo", + "level": "Allow", + "docs": { + "What it does": "Checks to see if all common metadata is defined in\n`Cargo.toml`. See: https://rust-lang-nursery.github.io/api-guidelines/documentation.html#cargotoml-includes-all-common-metadata-c-metadata", + "Why is this bad": "It will be more difficult for users to discover the\npurpose of the crate, and key information related to it.", + "Known problems": "None.", + "Example": "```toml\n# This `Cargo.toml` is missing an authors field:\n[package]\nname = \"clippy\"\nversion = \"0.0.212\"\nauthors = [\"Someone \"]\ndescription = \"A bunch of helpful lints to avoid common pitfalls in Rust\"\nrepository = \"https://github.com/rust-lang/rust-clippy\"\nreadme = \"README.md\"\nlicense = \"MIT OR Apache-2.0\"\nkeywords = [\"clippy\", \"lint\", \"plugin\"]\ncategories = [\"development-tools\", \"development-tools::cargo-plugins\"]\n```" + } + }, + { + "id": "cast_lossless", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for casts between numerical types that may\nbe replaced by safe conversion functions.", + "Why is this bad": "Rust's `as` keyword will perform many kinds of\nconversions, including silently lossy conversions. Conversion functions such\nas `i32::from` will only perform lossless conversions. Using the conversion\nfunctions prevents conversions from turning into silent lossy conversions if\nthe types of the input expressions ever change, and make it easier for\npeople reading the code to know that the conversion is lossless.", + "Known problems": "None.", + "Example": "```rust\nfn as_u64(x: u8) -> u64 {\n x as u64\n}\n```\n\nUsing `::from` would look like this:\n\n```rust\nfn as_u64(x: u8) -> u64 {\n u64::from(x)\n}\n```" + } + }, + { + "id": "cast_possible_truncation", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for casts between numerical types that may\ntruncate large values. This is expected behavior, so the cast is `Allow` by\ndefault.", + "Why is this bad": "In some problem domains, it is good practice to avoid\ntruncation. This lint can be activated to help assess where additional\nchecks could be beneficial.", + "Known problems": "None.", + "Example": "```rust\nfn as_u8(x: u64) -> u8 {\n x as u8\n}\n```" + } + }, + { + "id": "cast_possible_wrap", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for casts from an unsigned type to a signed type of\nthe same size. Performing such a cast is a 'no-op' for the compiler,\ni.e., nothing is changed at the bit level, and the binary representation of\nthe value is reinterpreted. This can cause wrapping if the value is too big\nfor the target signed type. However, the cast works as defined, so this lint\nis `Allow` by default.", + "Why is this bad": "While such a cast is not bad in itself, the results can\nbe surprising when this is not the intended behavior, as demonstrated by the\nexample below.", + "Known problems": "None.", + "Example": "```rust\nu32::MAX as i32; // will yield a value of `-1`\n```" + } + }, + { + "id": "cast_precision_loss", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for casts from any numerical to a float type where\nthe receiving type cannot store all values from the original type without\nrounding errors. This possible rounding is to be expected, so this lint is\n`Allow` by default.\n\nBasically, this warns on casting any integer with 32 or more bits to `f32`\nor any 64-bit integer to `f64`.", + "Why is this bad": "It's not bad at all. But in some applications it can be\nhelpful to know where precision loss can take place. This lint can help find\nthose places in the code.", + "Known problems": "None.", + "Example": "```rust\nlet x = u64::MAX;\nx as f64;\n```" + } + }, + { + "id": "cast_ptr_alignment", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for casts from a less-strictly-aligned pointer to a\nmore-strictly-aligned pointer", + "Why is this bad": "Dereferencing the resulting pointer may be undefined\nbehavior.", + "Known problems": "Using `std::ptr::read_unaligned` and `std::ptr::write_unaligned` or similar\non the resulting pointer is fine. Is over-zealous: Casts with manual alignment checks or casts like\nu64-> u8 -> u16 can be fine. Miri is able to do a more in-depth analysis.", + "Example": "```rust\nlet _ = (&1u8 as *const u8) as *const u16;\nlet _ = (&mut 1u8 as *mut u8) as *mut u16;\n```" + } + }, + { + "id": "cast_ref_to_mut", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for casts of `&T` to `&mut T` anywhere in the code.", + "Why is this bad": "It\u2019s basically guaranteed to be undefined behaviour.\n`UnsafeCell` is the only way to obtain aliasable data that is considered\nmutable.", + "Known problems": "None.", + "Example": "```rust,ignore\nfn x(r: &i32) {\n unsafe {\n *(r as *const _ as *mut _) += 1;\n }\n}\n```\n\nInstead consider using interior mutability types.\n\n```rust\nuse std::cell::UnsafeCell;\n\nfn x(r: &UnsafeCell) {\n unsafe {\n *r.get() += 1;\n }\n}\n```" + } + }, + { + "id": "cast_sign_loss", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for casts from a signed to an unsigned numerical\ntype. In this case, negative values wrap around to large positive values,\nwhich can be quite surprising in practice. However, as the cast works as\ndefined, this lint is `Allow` by default.", + "Why is this bad": "Possibly surprising results. You can activate this lint\nas a one-time check to see where numerical wrapping can arise.", + "Known problems": "None.", + "Example": "```rust\nlet y: i8 = -1;\ny as u128; // will return 18446744073709551615\n```" + } + }, + { + "id": "char_lit_as_u8", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for expressions where a character literal is cast\nto `u8` and suggests using a byte literal instead.", + "Why is this bad": "In general, casting values to smaller types is\nerror-prone and should be avoided where possible. In the particular case of\nconverting a character literal to u8, it is easy to avoid by just using a\nbyte literal instead. As an added bonus, `b'a'` is even slightly shorter\nthan `'a' as u8`.", + "Known problems": "None.", + "Example": "```rust,ignore\n'x' as u8\n```\n\nA better version, using the byte literal:\n\n```rust,ignore\nb'x'\n```" + } + }, + { + "id": "chars_last_cmp", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for usage of `_.chars().last()` or\n`_.chars().next_back()` on a `str` to check if it ends with a given char.", + "Why is this bad": "Readability, this can be written more concisely as\n`_.ends_with(_)`.", + "Known problems": "None.", + "Example": "```rust\n\n// Bad\nname.chars().last() == Some('_') || name.chars().next_back() == Some('-');\n\n// Good\nname.ends_with('_') || name.ends_with('-');\n```" + } + }, + { + "id": "chars_next_cmp", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for usage of `.chars().next()` on a `str` to check\nif it starts with a given char.", + "Why is this bad": "Readability, this can be written more concisely as\n`_.starts_with(_)`.", + "Known problems": "None.", + "Example": "```rust\nlet name = \"foo\";\nif name.chars().next() == Some('_') {};\n```\nCould be written as\n```rust\nlet name = \"foo\";\nif name.starts_with('_') {};\n```" + } + }, + { + "id": "checked_conversions", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for explicit bounds checking when casting.", + "Why is this bad": "Reduces the readability of statements & is error prone.", + "Known problems": "None.", + "Example": "```rust\nfoo <= i32::MAX as u32\n```\n\nCould be written:\n\n```rust\ni32::try_from(foo).is_ok()\n```" + } + }, + { + "id": "clone_double_ref", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for usage of `.clone()` on an `&&T`.", + "Why is this bad": "Cloning an `&&T` copies the inner `&T`, instead of\ncloning the underlying `T`.", + "Known problems": "None.", + "Example": "```rust\nfn main() {\n let x = vec![1];\n let y = &&x;\n let z = y.clone();\n println!(\"{:p} {:p}\", *y, z); // prints out the same pointer\n}\n```" + } + }, + { + "id": "clone_on_copy", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for usage of `.clone()` on a `Copy` type.", + "Why is this bad": "The only reason `Copy` types implement `Clone` is for\ngenerics, not for using the `clone` method on a concrete type.", + "Known problems": "None.", + "Example": "```rust\n42u64.clone();\n```" + } + }, + { + "id": "clone_on_ref_ptr", + "group": "restriction", + "level": "Allow", + "docs": { + "What it does": "Checks for usage of `.clone()` on a ref-counted pointer,\n(`Rc`, `Arc`, `rc::Weak`, or `sync::Weak`), and suggests calling Clone via unified\nfunction syntax instead (e.g., `Rc::clone(foo)`).", + "Why is this bad": "Calling '.clone()' on an Rc, Arc, or Weak\ncan obscure the fact that only the pointer is being cloned, not the underlying\ndata.", + "Example": "```rust\nlet x = Rc::new(1);\n\n// Bad\nx.clone();\n\n// Good\nRc::clone(&x);\n```" + } + }, + { + "id": "cmp_nan", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for comparisons to NaN.", + "Why is this bad": "NaN does not compare meaningfully to anything \u2013 not\neven itself \u2013 so those comparisons are simply wrong.", + "Known problems": "None.", + "Example": "```rust\n\n// Bad\nif x == f32::NAN { }\n\n// Good\nif x.is_nan() { }\n```" + } + }, + { + "id": "cmp_null", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "This lint checks for equality comparisons with `ptr::null`", + "Why is this bad": "It's easier and more readable to use the inherent\n`.is_null()`\nmethod instead", + "Known problems": "None.", + "Example": "```ignore\n// Bad\nif x == ptr::null {\n ..\n}\n\n// Good\nif x.is_null() {\n ..\n}\n```" + } + }, + { + "id": "cmp_owned", + "group": "perf", + "level": "Warn", + "docs": { + "What it does": "Checks for conversions to owned values just for the sake\nof a comparison.", + "Why is this bad": "The comparison can operate on a reference, so creating\nan owned value effectively throws it away directly afterwards, which is\nneedlessly consuming code and heap space.", + "Known problems": "None.", + "Example": "```rust\nif x.to_owned() == y {}\n```\nCould be written as\n```rust\nif x == y {}\n```" + } + }, + { + "id": "cognitive_complexity", + "group": "nursery", + "level": "Allow", + "docs": { + "What it does": "Checks for methods with high cognitive complexity.", + "Why is this bad": "Methods of high cognitive complexity tend to be hard to\nboth read and maintain. Also LLVM will tend to optimize small methods better.", + "Known problems": "Sometimes it's hard to find a way to reduce the\ncomplexity.", + "Example": "No. You'll see it when you get the warning.", + "Configuration": "This lint has the following configuration variables:\n\n* `cognitive-complexity-threshold: u64`: The maximum cognitive complexity a function can have (defaults to `25`)." + } + }, + { + "id": "collapsible_if", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for nested `if` statements which can be collapsed\nby `&&`-combining their conditions and for `else { if ... }` expressions\nthat\ncan be collapsed to `else if ...`.", + "Why is this bad": "Each `if`-statement adds one level of nesting, which\nmakes code look more complex than it really is.", + "Known problems": "None.", + "Example": "```rust,ignore\nif x {\n if y {\n \u2026\n }\n}\n\n// or\n\nif x {\n \u2026\n} else {\n if y {\n \u2026\n }\n}\n```\n\nShould be written:\n\n```rust.ignore\nif x && y {\n \u2026\n}\n\n// or\n\nif x {\n \u2026\n} else if y {\n \u2026\n}\n```" + } + }, + { + "id": "comparison_chain", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks comparison chains written with `if` that can be\nrewritten with `match` and `cmp`.", + "Why is this bad": "`if` is not guaranteed to be exhaustive and conditionals can get\nrepetitive", + "Known problems": "None.", + "Example": "```rust,ignore\nfn f(x: u8, y: u8) {\n if x > y {\n a()\n } else if x < y {\n b()\n } else {\n c()\n }\n}\n```\n\nCould be written:\n\n```rust,ignore\nuse std::cmp::Ordering;\nfn f(x: u8, y: u8) {\n match x.cmp(&y) {\n Ordering::Greater => a(),\n Ordering::Less => b(),\n Ordering::Equal => c()\n }\n}\n```" + } + }, + { + "id": "copy_iterator", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for types that implement `Copy` as well as\n`Iterator`.", + "Why is this bad": "Implicit copies can be confusing when working with\niterator combinators.", + "Known problems": "None.", + "Example": "```rust,ignore\n#[derive(Copy, Clone)]\nstruct Countdown(u8);\n\nimpl Iterator for Countdown {\n // ...\n}\n\nlet a: Vec<_> = my_iterator.take(1).collect();\nlet b: Vec<_> = my_iterator.collect();\n```" + } + }, + { + "id": "crosspointer_transmute", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for transmutes between a type `T` and `*T`.", + "Why is this bad": "It's easy to mistakenly transmute between a type and a\npointer to that type.", + "Known problems": "None.", + "Example": "```rust,ignore\ncore::intrinsics::transmute(t) // where the result type is the same as\n // `*t` or `&t`'s\n```" + } + }, + { + "id": "dbg_macro", + "group": "restriction", + "level": "Allow", + "docs": { + "What it does": "Checks for usage of dbg!() macro.", + "Why is this bad": "`dbg!` macro is intended as a debugging tool. It\nshould not be in version control.", + "Known problems": "None.", + "Example": "```rust,ignore\n// Bad\ndbg!(true)\n\n// Good\ntrue\n```" + } + }, + { + "id": "debug_assert_with_mut_call", + "group": "nursery", + "level": "Allow", + "docs": { + "What it does": "Checks for function/method calls with a mutable\nparameter in `debug_assert!`, `debug_assert_eq!` and `debug_assert_ne!` macros.", + "Why is this bad": "In release builds `debug_assert!` macros are optimized out by the\ncompiler.\nTherefore mutating something in a `debug_assert!` macro results in different behaviour\nbetween a release and debug build.", + "Known problems": "None", + "Example": "```rust,ignore\ndebug_assert_eq!(vec![3].pop(), Some(3));\n// or\nfn take_a_mut_parameter(_: &mut u32) -> bool { unimplemented!() }\ndebug_assert!(take_a_mut_parameter(&mut 5));\n```" + } + }, + { + "id": "decimal_literal_representation", + "group": "restriction", + "level": "Allow", + "docs": { + "What it does": "Warns if there is a better representation for a numeric literal.", + "Why is this bad": "Especially for big powers of 2 a hexadecimal representation is more\nreadable than a decimal representation.", + "Known problems": "None.", + "Example": "`255` => `0xFF`\n`65_535` => `0xFFFF`\n`4_042_322_160` => `0xF0F0_F0F0`", + "Configuration": "This lint has the following configuration variables:\n\n* `literal-representation-threshold: u64`: The lower bound for linting decimal literals (defaults to `16384`)." + } + }, + { + "id": "declare_interior_mutable_const", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for declaration of `const` items which is interior\nmutable (e.g., contains a `Cell`, `Mutex`, `AtomicXxxx`, etc.).", + "Why is this bad": "Consts are copied everywhere they are referenced, i.e.,\nevery time you refer to the const a fresh instance of the `Cell` or `Mutex`\nor `AtomicXxxx` will be created, which defeats the whole purpose of using\nthese types in the first place.\n\nThe `const` should better be replaced by a `static` item if a global\nvariable is wanted, or replaced by a `const fn` if a constructor is wanted.", + "Known problems": "A \"non-constant\" const item is a legacy way to supply an\ninitialized value to downstream `static` items (e.g., the\n`std::sync::ONCE_INIT` constant). In this case the use of `const` is legit,\nand this lint should be suppressed.", + "Example": "```rust\nuse std::sync::atomic::{AtomicUsize, Ordering::SeqCst};\n\n// Bad.\nconst CONST_ATOM: AtomicUsize = AtomicUsize::new(12);\nCONST_ATOM.store(6, SeqCst); // the content of the atomic is unchanged\nassert_eq!(CONST_ATOM.load(SeqCst), 12); // because the CONST_ATOM in these lines are distinct\n\n// Good.\nstatic STATIC_ATOM: AtomicUsize = AtomicUsize::new(15);\nSTATIC_ATOM.store(9, SeqCst);\nassert_eq!(STATIC_ATOM.load(SeqCst), 9); // use a `static` item to refer to the same instance\n```" + } + }, + { + "id": "default_trait_access", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for literal calls to `Default::default()`.", + "Why is this bad": "It's more clear to the reader to use the name of the type whose default is\nbeing gotten than the generic `Default`.", + "Known problems": "None.", + "Example": "```rust\n// Bad\nlet s: String = Default::default();\n\n// Good\nlet s = String::default();\n```" + } + }, + { + "id": "deprecated_cfg_attr", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for `#[cfg_attr(rustfmt, rustfmt_skip)]` and suggests to replace it\nwith `#[rustfmt::skip]`.", + "Why is this bad": "Since tool_attributes ([rust-lang/rust#44690](https://github.com/rust-lang/rust/issues/44690))\nare stable now, they should be used instead of the old `cfg_attr(rustfmt)` attributes.", + "Known problems": "This lint doesn't detect crate level inner attributes, because they get\nprocessed before the PreExpansionPass lints get executed. See\n[#3123](https://github.com/rust-lang/rust-clippy/pull/3123#issuecomment-422321765)", + "Example": "Bad:\n```rust\n#[cfg_attr(rustfmt, rustfmt_skip)]\nfn main() { }\n```\n\nGood:\n```rust\n#[rustfmt::skip]\nfn main() { }\n```" + } + }, + { + "id": "deprecated_semver", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for `#[deprecated]` annotations with a `since`\nfield that is not a valid semantic version.", + "Why is this bad": "For checking the version of the deprecation, it must be\na valid semver. Failing that, the contained information is useless.", + "Known problems": "None.", + "Example": "```rust\n#[deprecated(since = \"forever\")]\nfn something_else() { /* ... */ }\n```" + } + }, + { + "id": "deref_addrof", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for usage of `*&` and `*&mut` in expressions.", + "Why is this bad": "Immediately dereferencing a reference is no-op and\nmakes the code less clear.", + "Known problems": "Multiple dereference/addrof pairs are not handled so\nthe suggested fix for `x = **&&y` is `x = *&y`, which is still incorrect.", + "Example": "```rust,ignore\n// Bad\nlet a = f(*&mut b);\nlet c = *&d;\n\n// Good\nlet a = f(b);\nlet c = d;\n```" + } + }, + { + "id": "derive_hash_xor_eq", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for deriving `Hash` but implementing `PartialEq`\nexplicitly or vice versa.", + "Why is this bad": "The implementation of these traits must agree (for\nexample for use with `HashMap`) so it\u2019s probably a bad idea to use a\ndefault-generated `Hash` implementation with an explicitly defined\n`PartialEq`. In particular, the following must hold for any type:\n\n```text\nk1 == k2 \u21d2 hash(k1) == hash(k2)\n```", + "Known problems": "None.", + "Example": "```ignore\n#[derive(Hash)]\nstruct Foo;\n\nimpl PartialEq for Foo {\n ...\n}\n```" + } + }, + { + "id": "diverging_sub_expression", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for diverging calls that are not match arms or\nstatements.", + "Why is this bad": "It is often confusing to read. In addition, the\nsub-expression evaluation order for Rust is not well documented.", + "Known problems": "Someone might want to use `some_bool || panic!()` as a\nshorthand.", + "Example": "```rust,no_run\nlet a = b() || panic!() || c();\n// `c()` is dead, `panic!()` is only called if `b()` returns `false`\nlet x = (a, b, c, panic!());\n// can simply be replaced by `panic!()`\n```" + } + }, + { + "id": "doc_markdown", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for the presence of `_`, `::` or camel-case words\noutside ticks in documentation.", + "Why is this bad": "*Rustdoc* supports markdown formatting, `_`, `::` and\ncamel-case probably indicates some code which should be included between\nticks. `_` can also be used for emphasis in markdown, this lint tries to\nconsider that.", + "Known problems": "Lots of bad docs won\u2019t be fixed, what the lint checks\nfor is limited, and there are still false positives.", + "Examples": "```rust\n/// Do something with the foo_bar parameter. See also\n/// that::other::module::foo.\n// ^ `foo_bar` and `that::other::module::foo` should be ticked.\nfn doit(foo_bar: usize) {}\n```", + "Configuration": "This lint has the following configuration variables:\n\n* `doc-valid-idents: Vec`: The list of words this lint should not consider as identifiers needing ticks (defaults to `[\n \"KiB\", \"MiB\", \"GiB\", \"TiB\", \"PiB\", \"EiB\",\n \"DirectX\",\n \"ECMAScript\",\n \"GPLv2\", \"GPLv3\",\n \"GitHub\", \"GitLab\",\n \"IPv4\", \"IPv6\",\n \"ClojureScript\", \"CoffeeScript\", \"JavaScript\", \"PureScript\", \"TypeScript\",\n \"NaN\", \"NaNs\",\n \"OAuth\",\n \"OCaml\",\n \"OpenGL\", \"OpenMP\", \"OpenSSH\", \"OpenSSL\", \"OpenStreetMap\",\n \"TensorFlow\",\n \"TrueType\",\n \"iOS\", \"macOS\",\n \"TeX\", \"LaTeX\", \"BibTeX\", \"BibLaTeX\",\n \"MinGW\",\n \"CamelCase\",\n ]`)." + } + }, + { + "id": "double_comparisons", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for double comparisons that could be simplified to a single expression.", + "Why is this bad": "Readability.", + "Known problems": "None.", + "Example": "```rust\nif x == y || x < y {}\n```\n\nCould be written as:\n\n```rust\nif x <= y {}\n```" + } + }, + { + "id": "double_must_use", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for a [`#[must_use]`] attribute without\nfurther information on functions and methods that return a type already\nmarked as `#[must_use]`.\n\n[`#[must_use]`]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute", + "Why is this bad": "The attribute isn't needed. Not using the result\nwill already be reported. Alternatively, one can add some text to the\nattribute to improve the lint message.", + "Known problems": "None.", + "Examples": "```rust\n#[must_use]\nfn double_must_use() -> Result<(), ()> {\n unimplemented!();\n}\n```" + } + }, + { + "id": "double_neg", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Detects expressions of the form `--x`.", + "Why is this bad": "It can mislead C/C++ programmers to think `x` was\ndecremented.", + "Known problems": "None.", + "Example": "```rust\nlet mut x = 3;\n--x;\n```" + } + }, + { + "id": "double_parens", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for unnecessary double parentheses.", + "Why is this bad": "This makes code harder to read and might indicate a\nmistake.", + "Known problems": "None.", + "Example": "```rust\n// Bad\nfn simple_double_parens() -> i32 {\n ((0))\n}\n\n// Good\nfn simple_no_parens() -> i32 {\n 0\n}\n\n// or\n\n// Bad\nfoo((0));\n\n// Good\nfoo(0);\n```" + } + }, + { + "id": "drop_bounds", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for generics with `std::ops::Drop` as bounds.", + "Why is this bad": "`Drop` bounds do not really accomplish anything.\nA type may have compiler-generated drop glue without implementing the\n`Drop` trait itself. The `Drop` trait also only has one method,\n`Drop::drop`, and that function is by fiat not callable in user code.\nSo there is really no use case for using `Drop` in trait bounds.\n\nThe most likely use case of a drop bound is to distinguish between types\nthat have destructors and types that don't. Combined with specialization,\na naive coder would write an implementation that assumed a type could be\ntrivially dropped, then write a specialization for `T: Drop` that actually\ncalls the destructor. Except that doing so is not correct; String, for\nexample, doesn't actually implement Drop, but because String contains a\nVec, assuming it can be trivially dropped will leak memory.", + "Known problems": "None.", + "Example": "```rust\nfn foo() {}\n```\nCould be written as:\n```rust\nfn foo() {}\n```" + } + }, + { + "id": "drop_copy", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for calls to `std::mem::drop` with a value\nthat derives the Copy trait", + "Why is this bad": "Calling `std::mem::drop` [does nothing for types that\nimplement Copy](https://doc.rust-lang.org/std/mem/fn.drop.html), since the\nvalue will be copied and moved into the function on invocation.", + "Known problems": "None.", + "Example": "```rust\nlet x: i32 = 42; // i32 implements Copy\nstd::mem::drop(x) // A copy of x is passed to the function, leaving the\n // original unaffected\n```" + } + }, + { + "id": "drop_ref", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for calls to `std::mem::drop` with a reference\ninstead of an owned value.", + "Why is this bad": "Calling `drop` on a reference will only drop the\nreference itself, which is a no-op. It will not call the `drop` method (from\nthe `Drop` trait implementation) on the underlying referenced value, which\nis likely what was intended.", + "Known problems": "None.", + "Example": "```ignore\nlet mut lock_guard = mutex.lock();\nstd::mem::drop(&lock_guard) // Should have been drop(lock_guard), mutex\n// still locked\noperation_that_requires_mutex_to_be_unlocked();\n```" + } + }, + { + "id": "duplicate_underscore_argument", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for function arguments having the similar names\ndiffering by an underscore.", + "Why is this bad": "It affects code readability.", + "Known problems": "None.", + "Example": "```rust\n// Bad\nfn foo(a: i32, _a: i32) {}\n\n// Good\nfn bar(a: i32, _b: i32) {}\n```" + } + }, + { + "id": "duration_subsec", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for calculation of subsecond microseconds or milliseconds\nfrom other `Duration` methods.", + "Why is this bad": "It's more concise to call `Duration::subsec_micros()` or\n`Duration::subsec_millis()` than to calculate them.", + "Known problems": "None.", + "Example": "```rust\nlet dur = Duration::new(5, 0);\n\n// Bad\nlet _micros = dur.subsec_nanos() / 1_000;\nlet _millis = dur.subsec_nanos() / 1_000_000;\n\n// Good\nlet _micros = dur.subsec_micros();\nlet _millis = dur.subsec_millis();\n```" + } + }, + { + "id": "else_if_without_else", + "group": "restriction", + "level": "Allow", + "docs": { + "What it does": "Checks for usage of if expressions with an `else if` branch,\nbut without a final `else` branch.", + "Why is this bad": "Some coding guidelines require this (e.g., MISRA-C:2004 Rule 14.10).", + "Known problems": "None.", + "Example": "```rust\nif x.is_positive() {\n a();\n} else if x.is_negative() {\n b();\n}\n```\n\nCould be written:\n\n```rust\nif x.is_positive() {\n a();\n} else if x.is_negative() {\n b();\n} else {\n // We don't care about zero.\n}\n```" + } + }, + { + "id": "empty_enum", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for `enum`s with no variants.", + "Why is this bad": "If you want to introduce a type which\ncan't be instantiated, you should use `!` (the never type),\nor a wrapper around it, because `!` has more extensive\ncompiler support (type inference, etc...) and wrappers\naround it are the conventional way to define an uninhabited type.\nFor further information visit [never type documentation](https://doc.rust-lang.org/std/primitive.never.html)", + "Known problems": "None.", + "Example": "Bad:\n```rust\nenum Test {}\n```\n\nGood:\n```rust\n#![feature(never_type)]\n\nstruct Test(!);\n```" + } + }, + { + "id": "empty_line_after_outer_attr", + "group": "nursery", + "level": "Allow", + "docs": { + "What it does": "Checks for empty lines after outer attributes", + "Why is this bad": "Most likely the attribute was meant to be an inner attribute using a '!'.\nIf it was meant to be an outer attribute, then the following item\nshould not be separated by empty lines.", + "Known problems": "Can cause false positives.\n\nFrom the clippy side it's difficult to detect empty lines between an attributes and the\nfollowing item because empty lines and comments are not part of the AST. The parsing\ncurrently works for basic cases but is not perfect.", + "Example": "```rust\n// Good (as inner attribute)\n#![inline(always)]\n\nfn this_is_fine() { }\n\n// Bad\n#[inline(always)]\n\nfn not_quite_good_code() { }\n\n// Good (as outer attribute)\n#[inline(always)]\nfn this_is_fine_too() { }\n```" + } + }, + { + "id": "empty_loop", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for empty `loop` expressions.", + "Why is this bad": "Those busy loops burn CPU cycles without doing\nanything. Think of the environment and either block on something or at least\nmake the thread sleep for some microseconds.", + "Known problems": "None.", + "Example": "```no_run\nloop {}\n```" + } + }, + { + "id": "enum_clike_unportable_variant", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for C-like enumerations that are\n`repr(isize/usize)` and have values that don't fit into an `i32`.", + "Why is this bad": "This will truncate the variant value on 32 bit\narchitectures, but works fine on 64 bit.", + "Known problems": "None.", + "Example": "```rust\n#[repr(usize)]\nenum NonPortable {\n X = 0x1_0000_0000,\n Y = 0,\n}\n```" + } + }, + { + "id": "enum_glob_use", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for `use Enum::*`.", + "Why is this bad": "It is usually better style to use the prefixed name of\nan enumeration variant, rather than importing variants.", + "Known problems": "Old-style enumerations that prefix the variants are\nstill around.", + "Example": "```rust,ignore\n// Bad\nuse std::cmp::Ordering::*;\nfoo(Less);\n\n// Good\nuse std::cmp::Ordering;\nfoo(Ordering::Less)\n```" + } + }, + { + "id": "enum_variant_names", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Detects enumeration variants that are prefixed or suffixed\nby the same characters.", + "Why is this bad": "Enumeration variant names should specify their variant,\nnot repeat the enumeration name.", + "Known problems": "None.", + "Example": "```rust\nenum Cake {\n BlackForestCake,\n HummingbirdCake,\n BattenbergCake,\n}\n```\nCould be written as:\n```rust\nenum Cake {\n BlackForest,\n Hummingbird,\n Battenberg,\n}\n```", + "Configuration": "This lint has the following configuration variables:\n\n* `enum-variant-name-threshold: u64`: The minimum number of enum variants for the lints about variant names to trigger (defaults to `3`)." + } + }, + { + "id": "eq_op", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for equal operands to comparison, logical and\nbitwise, difference and division binary operators (`==`, `>`, etc., `&&`,\n`||`, `&`, `|`, `^`, `-` and `/`).", + "Why is this bad": "This is usually just a typo or a copy and paste error.", + "Known problems": "False negatives: We had some false positives regarding\ncalls (notably [racer](https://github.com/phildawes/racer) had one instance\nof `x.pop() && x.pop()`), so we removed matching any function or method\ncalls. We may introduce a whitelist of known pure functions in the future.", + "Example": "```rust\nif x + 1 == x + 1 {}\n```" + } + }, + { + "id": "erasing_op", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for erasing operations, e.g., `x * 0`.", + "Why is this bad": "The whole expression can be replaced by zero.\nThis is most likely not the intended outcome and should probably be\ncorrected", + "Known problems": "None.", + "Example": "```rust\nlet x = 1;\n0 / x;\n0 * x;\nx & 0;\n```" + } + }, + { + "id": "eval_order_dependence", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for a read and a write to the same variable where\nwhether the read occurs before or after the write depends on the evaluation\norder of sub-expressions.", + "Why is this bad": "It is often confusing to read. In addition, the\nsub-expression evaluation order for Rust is not well documented.", + "Known problems": "Code which intentionally depends on the evaluation\norder, or which is correct for any evaluation order.", + "Example": "```rust\nlet mut x = 0;\n\n// Bad\nlet a = {\n x = 1;\n 1\n} + x;\n// Unclear whether a is 1 or 2.\n\n// Good\nlet tmp = {\n x = 1;\n 1\n};\nlet a = tmp + x;\n```" + } + }, + { + "id": "excessive_precision", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for float literals with a precision greater\nthan that supported by the underlying type.", + "Why is this bad": "Rust will truncate the literal silently.", + "Known problems": "None.", + "Example": "```rust\n// Bad\nlet v: f32 = 0.123_456_789_9;\nprintln!(\"{}\", v); // 0.123_456_789\n\n// Good\nlet v: f64 = 0.123_456_789_9;\nprintln!(\"{}\", v); // 0.123_456_789_9\n```" + } + }, + { + "id": "exit", + "group": "restriction", + "level": "Allow", + "docs": { + "What it does": "`exit()` terminates the program and doesn't provide a\nstack trace.", + "Why is this bad": "Ideally a program is terminated by finishing\nthe main function.", + "Known problems": "None.", + "Example": "```ignore\nstd::process::exit(0)\n```" + } + }, + { + "id": "expect_fun_call", + "group": "perf", + "level": "Warn", + "docs": { + "What it does": "Checks for calls to `.expect(&format!(...))`, `.expect(foo(..))`,\netc., and suggests to use `unwrap_or_else` instead", + "Why is this bad": "The function will always be called.", + "Known problems": "If the function has side-effects, not calling it will\nchange the semantics of the program, but you shouldn't rely on that anyway.", + "Example": "```rust\nfoo.expect(&format!(\"Err {}: {}\", err_code, err_msg));\n```\nor\n```rust\nfoo.expect(format!(\"Err {}: {}\", err_code, err_msg).as_str());\n```\nthis can instead be written:\n```rust\nfoo.unwrap_or_else(|| panic!(\"Err {}: {}\", err_code, err_msg));\n```" + } + }, + { + "id": "expect_used", + "group": "restriction", + "level": "Allow", + "docs": { + "What it does": "Checks for `.expect()` calls on `Option`s and `Result`s.", + "Why is this bad": "Usually it is better to handle the `None` or `Err` case.\nStill, for a lot of quick-and-dirty code, `expect` is a good choice, which is why\nthis lint is `Allow` by default.\n\n`result.expect()` will let the thread panic on `Err`\nvalues. Normally, you want to implement more sophisticated error handling,\nand propagate errors upwards with `?` operator.", + "Known problems": "None.", + "Examples": "```rust,ignore\n\n// Bad\nopt.expect(\"one\");\n\n// Good\nlet opt = Some(1);\nopt?;\n```\n\n// or\n\n```rust\n\n// Bad\nres.expect(\"one\");\n\n// Good\nres?;\n```" + } + }, + { + "id": "expl_impl_clone_on_copy", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for explicit `Clone` implementations for `Copy`\ntypes.", + "Why is this bad": "To avoid surprising behaviour, these traits should\nagree and the behaviour of `Copy` cannot be overridden. In almost all\nsituations a `Copy` type should have a `Clone` implementation that does\nnothing more than copy the object, which is what `#[derive(Copy, Clone)]`\ngets you.", + "Known problems": "Bounds of generic types are sometimes wrong: https://github.com/rust-lang/rust/issues/26925", + "Example": "```rust,ignore\n#[derive(Copy)]\nstruct Foo;\n\nimpl Clone for Foo {\n // ..\n}\n```" + } + }, + { + "id": "explicit_counter_loop", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks `for` loops over slices with an explicit counter\nand suggests the use of `.enumerate()`.", + "Why is it bad": "Using `.enumerate()` makes the intent more clear,\ndeclutters the code and may be faster in some instances.", + "Known problems": "None.", + "Example": "```rust\nlet mut i = 0;\nfor item in &v {\n bar(i, *item);\n i += 1;\n}\n```\nCould be written as\n```rust\nfor (i, item) in v.iter().enumerate() { bar(i, *item); }\n```" + } + }, + { + "id": "explicit_deref_methods", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for explicit `deref()` or `deref_mut()` method calls.", + "Why is this bad": "Derefencing by `&*x` or `&mut *x` is clearer and more concise,\nwhen not part of a method chain.", + "Example": "```rust\nuse std::ops::Deref;\nlet a: &mut String = &mut String::from(\"foo\");\nlet b: &str = a.deref();\n```\nCould be written as:\n```rust\nlet a: &mut String = &mut String::from(\"foo\");\nlet b = &*a;\n```\n\nThis lint excludes\n```rust,ignore\nlet _ = d.unwrap().deref();\n```" + } + }, + { + "id": "explicit_into_iter_loop", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for loops on `y.into_iter()` where `y` will do, and\nsuggests the latter.", + "Why is this bad": "Readability.", + "Known problems": "None", + "Example": "```rust\n// with `y` a `Vec` or slice:\nfor x in y.into_iter() {\n // ..\n}\n```\ncan be rewritten to\n```rust\nfor x in y {\n // ..\n}\n```" + } + }, + { + "id": "explicit_iter_loop", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for loops on `x.iter()` where `&x` will do, and\nsuggests the latter.", + "Why is this bad": "Readability.", + "Known problems": "False negatives. We currently only warn on some known\ntypes.", + "Example": "```rust\n// with `y` a `Vec` or slice:\nfor x in y.iter() {\n // ..\n}\n```\ncan be rewritten to\n```rust\nfor x in &y {\n // ..\n}\n```" + } + }, + { + "id": "explicit_write", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for usage of `write!()` / `writeln()!` which can be\nreplaced with `(e)print!()` / `(e)println!()`", + "Why is this bad": "Using `(e)println! is clearer and more concise", + "Known problems": "None.", + "Example": "```rust\n// this would be clearer as `eprintln!(\"foo: {:?}\", bar);`\nwriteln!(&mut std::io::stderr(), \"foo: {:?}\", bar).unwrap();\n```" + } + }, + { + "id": "extend_from_slice", + "group": "deprecated", + "level": "Deprecated", + "docs": { + "What it does": "Nothing. This lint has been deprecated.", + "Deprecation reason": "This used to check for `Vec::extend`, which was slower than\n`Vec::extend_from_slice`. Thanks to specialization, this is no longer true." + } + }, + { + "id": "extra_unused_lifetimes", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for lifetimes in generics that are never used\nanywhere else.", + "Why is this bad": "The additional lifetimes make the code look more\ncomplicated, while there is nothing out of the ordinary going on. Removing\nthem leads to more readable code.", + "Known problems": "None.", + "Example": "```rust\n// Bad: unnecessary lifetimes\nfn unused_lifetime<'a>(x: u8) {\n // ..\n}\n\n// Good\nfn no_lifetime(x: u8) {\n // ...\n}\n```" + } + }, + { + "id": "fallible_impl_from", + "group": "nursery", + "level": "Allow", + "docs": { + "What it does": "Checks for impls of `From<..>` that contain `panic!()` or `unwrap()`", + "Why is this bad": "`TryFrom` should be used if there's a possibility of failure.", + "Known problems": "None.", + "Example": "```rust\nstruct Foo(i32);\n\n// Bad\nimpl From for Foo {\n fn from(s: String) -> Self {\n Foo(s.parse().unwrap())\n }\n}\n```\n\n```rust\n// Good\nstruct Foo(i32);\n\nuse std::convert::TryFrom;\nimpl TryFrom for Foo {\n type Error = ();\n fn try_from(s: String) -> Result {\n if let Ok(parsed) = s.parse() {\n Ok(Foo(parsed))\n } else {\n Err(())\n }\n }\n}\n```" + } + }, + { + "id": "filetype_is_file", + "group": "restriction", + "level": "Allow", + "docs": { + "What it does": "Checks for `FileType::is_file()`.", + "Why is this bad": "When people testing a file type with `FileType::is_file`\nthey are testing whether a path is something they can get bytes from. But\n`is_file` doesn't cover special file types in unix-like systems, and doesn't cover\nsymlink in windows. Using `!FileType::is_dir()` is a better way to that intention.", + "Example": "```rust\nlet metadata = std::fs::metadata(\"foo.txt\")?;\nlet filetype = metadata.file_type();\n\nif filetype.is_file() {\n // read file\n}\n```\n\nshould be written as:\n\n```rust\nlet metadata = std::fs::metadata(\"foo.txt\")?;\nlet filetype = metadata.file_type();\n\nif !filetype.is_dir() {\n // read file\n}\n```" + } + }, + { + "id": "filter_map", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for usage of `_.filter(_).map(_)`,\n`_.filter(_).flat_map(_)`, `_.filter_map(_).flat_map(_)` and similar.", + "Why is this bad": "Readability, this can be written more concisely as a\nsingle method call.", + "Known problems": "Often requires a condition + Option/Iterator creation\ninside the closure.", + "Example": "```rust\nlet vec = vec![1];\n\n// Bad\nvec.iter().filter(|x| **x == 0).map(|x| *x * 2);\n\n// Good\nvec.iter().filter_map(|x| if *x == 0 {\n Some(*x * 2)\n} else {\n None\n});\n```" + } + }, + { + "id": "filter_map_next", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for usage of `_.filter_map(_).next()`.", + "Why is this bad": "Readability, this can be written more concisely as a\nsingle method call.", + "Known problems": "None", + "Example": "```rust\n (0..3).filter_map(|x| if x == 2 { Some(x) } else { None }).next();\n```\nCan be written as\n\n```rust\n (0..3).find_map(|x| if x == 2 { Some(x) } else { None });\n```" + } + }, + { + "id": "filter_next", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for usage of `_.filter(_).next()`.", + "Why is this bad": "Readability, this can be written more concisely as\n`_.find(_)`.", + "Known problems": "None.", + "Example": "```rust\nvec.iter().filter(|x| **x == 0).next();\n```\nCould be written as\n```rust\nvec.iter().find(|x| **x == 0);\n```" + } + }, + { + "id": "find_map", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for usage of `_.find(_).map(_)`.", + "Why is this bad": "Readability, this can be written more concisely as a\nsingle method call.", + "Known problems": "Often requires a condition + Option/Iterator creation\ninside the closure.", + "Example": "```rust\n (0..3).find(|x| *x == 2).map(|x| x * 2);\n```\nCan be written as\n```rust\n (0..3).find_map(|x| if x == 2 { Some(x * 2) } else { None });\n```" + } + }, + { + "id": "flat_map_identity", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for usage of `flat_map(|x| x)`.", + "Why is this bad": "Readability, this can be written more concisely by using `flatten`.", + "Known problems": "None", + "Example": "```rust\niter.flat_map(|x| x);\n```\nCan be written as\n```rust\niter.flatten();\n```" + } + }, + { + "id": "float_arithmetic", + "group": "restriction", + "level": "Allow", + "docs": { + "What it does": "Checks for float arithmetic.", + "Why is this bad": "For some embedded systems or kernel development, it\ncan be useful to rule out floating-point numbers.", + "Known problems": "None.", + "Example": "```rust\na + 1.0;\n```" + } + }, + { + "id": "float_cmp", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for (in-)equality comparisons on floating-point\nvalues (apart from zero), except in functions called `*eq*` (which probably\nimplement equality for a type involving floats).", + "Why is this bad": "Floating point calculations are usually imprecise, so\nasking if two values are *exactly* equal is asking for trouble. For a good\nguide on what to do, see [the floating point\nguide](http://www.floating-point-gui.de/errors/comparison).", + "Known problems": "None.", + "Example": "```rust\nlet x = 1.2331f64;\nlet y = 1.2332f64;\n\n// Bad\nif y == 1.23f64 { }\nif y != x {} // where both are floats\n\n// Good\nlet error = 0.01f64; // Use an epsilon for comparison\nif (y - 1.23f64).abs() < error { }\nif (y - x).abs() > error { }\n```" + } + }, + { + "id": "float_cmp_const", + "group": "restriction", + "level": "Allow", + "docs": { + "What it does": "Checks for (in-)equality comparisons on floating-point\nvalue and constant, except in functions called `*eq*` (which probably\nimplement equality for a type involving floats).", + "Why is this bad": "Floating point calculations are usually imprecise, so\nasking if two values are *exactly* equal is asking for trouble. For a good\nguide on what to do, see [the floating point\nguide](http://www.floating-point-gui.de/errors/comparison).", + "Known problems": "None.", + "Example": "```rust\nlet x: f64 = 1.0;\nconst ONE: f64 = 1.00;\n\n// Bad\nif x == ONE { } // where both are floats\n\n// Good\nlet error = 0.1f64; // Use an epsilon for comparison\nif (x - ONE).abs() < error { }\n```" + } + }, + { + "id": "fn_address_comparisons", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for comparisons with an address of a function item.", + "Why is this bad": "Function item address is not guaranteed to be unique and could vary\nbetween different code generation units. Furthermore different function items could have\nthe same address after being merged together.", + "Known problems": "None.", + "Example": "```rust\ntype F = fn();\nfn a() {}\nlet f: F = a;\nif f == a {\n // ...\n}\n```" + } + }, + { + "id": "fn_params_excessive_bools", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for excessive use of\nbools in function definitions.", + "Why is this bad": "Calls to such functions\nare confusing and error prone, because it's\nhard to remember argument order and you have\nno type system support to back you up. Using\ntwo-variant enums instead of bools often makes\nAPI easier to use.", + "Known problems": "None.", + "Example": "Bad:\n```rust,ignore\nfn f(is_round: bool, is_hot: bool) { ... }\n```\n\nGood:\n```rust,ignore\nenum Shape {\n Round,\n Spiky,\n}\n\nenum Temperature {\n Hot,\n IceCold,\n}\n\nfn f(shape: Shape, temperature: Temperature) { ... }\n```", + "Configuration": "This lint has the following configuration variables:\n\n* `max-fn-params-bools: u64`: The maximum number of bools function parameters can have (defaults to `3`)." + } + }, + { + "id": "fn_to_numeric_cast", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for casts of function pointers to something other than usize", + "Why is this bad": "Casting a function pointer to anything other than usize/isize is not portable across\narchitectures, because you end up losing bits if the target type is too small or end up with a\nbunch of extra bits that waste space and add more instructions to the final binary than\nstrictly necessary for the problem\n\nCasting to isize also doesn't make sense since there are no signed addresses.", + "Example": "```rust\n// Bad\nfn fun() -> i32 { 1 }\nlet a = fun as i64;\n\n// Good\nfn fun2() -> i32 { 1 }\nlet a = fun2 as usize;\n```" + } + }, + { + "id": "fn_to_numeric_cast_with_truncation", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for casts of a function pointer to a numeric type not wide enough to\nstore address.", + "Why is this bad": "Such a cast discards some bits of the function's address. If this is intended, it would be more\nclearly expressed by casting to usize first, then casting the usize to the intended type (with\na comment) to perform the truncation.", + "Example": "```rust\n// Bad\nfn fn1() -> i16 {\n 1\n};\nlet _ = fn1 as i32;\n\n// Better: Cast to usize first, then comment with the reason for the truncation\nfn fn2() -> i16 {\n 1\n};\nlet fn_ptr = fn2 as usize;\nlet fn_ptr_truncated = fn_ptr as i32;\n```" + } + }, + { + "id": "for_kv_map", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for iterating a map (`HashMap` or `BTreeMap`) and\nignoring either the keys or values.", + "Why is this bad": "Readability. There are `keys` and `values` methods that\ncan be used to express that don't need the values or keys.", + "Known problems": "None.", + "Example": "```ignore\nfor (k, _) in &map {\n ..\n}\n```\n\ncould be replaced by\n\n```ignore\nfor k in map.keys() {\n ..\n}\n```" + } + }, + { + "id": "for_loops_over_fallibles", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for `for` loops over `Option` or `Result` values.", + "Why is this bad": "Readability. This is more clearly expressed as an `if\nlet`.", + "Known problems": "None.", + "Example": "```rust\n\n// Bad\nfor x in opt {\n // ..\n}\n\n// Good\nif let Some(x) = opt {\n // ..\n}\n```\n\n// or\n\n```rust\n\n// Bad\nfor x in &res {\n // ..\n}\n\n// Good\nif let Ok(x) = res {\n // ..\n}\n```" + } + }, + { + "id": "forget_copy", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for calls to `std::mem::forget` with a value that\nderives the Copy trait", + "Why is this bad": "Calling `std::mem::forget` [does nothing for types that\nimplement Copy](https://doc.rust-lang.org/std/mem/fn.drop.html) since the\nvalue will be copied and moved into the function on invocation.\n\nAn alternative, but also valid, explanation is that Copy types do not\nimplement\nthe Drop trait, which means they have no destructors. Without a destructor,\nthere\nis nothing for `std::mem::forget` to ignore.", + "Known problems": "None.", + "Example": "```rust\nlet x: i32 = 42; // i32 implements Copy\nstd::mem::forget(x) // A copy of x is passed to the function, leaving the\n // original unaffected\n```" + } + }, + { + "id": "forget_ref", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for calls to `std::mem::forget` with a reference\ninstead of an owned value.", + "Why is this bad": "Calling `forget` on a reference will only forget the\nreference itself, which is a no-op. It will not forget the underlying\nreferenced\nvalue, which is likely what was intended.", + "Known problems": "None.", + "Example": "```rust\nlet x = Box::new(1);\nstd::mem::forget(&x) // Should have been forget(x), x will still be dropped\n```" + } + }, + { + "id": "future_not_send", + "group": "nursery", + "level": "Allow", + "docs": { + "What it does": "This lint requires Future implementations returned from\nfunctions and methods to implement the `Send` marker trait. It is mostly\nused by library authors (public and internal) that target an audience where\nmultithreaded executors are likely to be used for running these Futures.", + "Why is this bad": "A Future implementation captures some state that it\nneeds to eventually produce its final value. When targeting a multithreaded\nexecutor (which is the norm on non-embedded devices) this means that this\nstate may need to be transported to other threads, in other words the\nwhole Future needs to implement the `Send` marker trait. If it does not,\nthen the resulting Future cannot be submitted to a thread pool in the\nend user\u2019s code.\n\nEspecially for generic functions it can be confusing to leave the\ndiscovery of this problem to the end user: the reported error location\nwill be far from its cause and can in many cases not even be fixed without\nmodifying the library where the offending Future implementation is\nproduced.", + "Known problems": "None.", + "Example": "```rust\nasync fn not_send(bytes: std::rc::Rc<[u8]>) {}\n```\nUse instead:\n```rust\nasync fn is_send(bytes: std::sync::Arc<[u8]>) {}\n```" + } + }, + { + "id": "get_last_with_len", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for using `x.get(x.len() - 1)` instead of\n`x.last()`.", + "Why is this bad": "Using `x.last()` is easier to read and has the same\nresult.\n\nNote that using `x[x.len() - 1]` is semantically different from\n`x.last()`. Indexing into the array will panic on out-of-bounds\naccesses, while `x.get()` and `x.last()` will return `None`.\n\nThere is another lint (get_unwrap) that covers the case of using\n`x.get(index).unwrap()` instead of `x[index]`.", + "Known problems": "None.", + "Example": "```rust\n// Bad\nlet x = vec![2, 3, 5];\nlet last_element = x.get(x.len() - 1);\n\n// Good\nlet x = vec![2, 3, 5];\nlet last_element = x.last();\n```" + } + }, + { + "id": "get_unwrap", + "group": "restriction", + "level": "Allow", + "docs": { + "What it does": "Checks for use of `.get().unwrap()` (or\n`.get_mut().unwrap`) on a standard library type which implements `Index`", + "Why is this bad": "Using the Index trait (`[]`) is more clear and more\nconcise.", + "Known problems": "Not a replacement for error handling: Using either\n`.unwrap()` or the Index trait (`[]`) carries the risk of causing a `panic`\nif the value being accessed is `None`. If the use of `.get().unwrap()` is a\ntemporary placeholder for dealing with the `Option` type, then this does\nnot mitigate the need for error handling. If there is a chance that `.get()`\nwill be `None` in your program, then it is advisable that the `None` case\nis handled in a future refactor instead of using `.unwrap()` or the Index\ntrait.", + "Example": "```rust\nlet mut some_vec = vec![0, 1, 2, 3];\nlet last = some_vec.get(3).unwrap();\n*some_vec.get_mut(0).unwrap() = 1;\n```\nThe correct use would be:\n```rust\nlet mut some_vec = vec![0, 1, 2, 3];\nlet last = some_vec[3];\nsome_vec[0] = 1;\n```" + } + }, + { + "id": "identity_op", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for identity operations, e.g., `x + 0`.", + "Why is this bad": "This code can be removed without changing the\nmeaning. So it just obscures what's going on. Delete it mercilessly.", + "Known problems": "None.", + "Example": "```rust\nx / 1 + 0 * 1 - 0 | 0;\n```" + } + }, + { + "id": "if_let_mutex", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for `Mutex::lock` calls in `if let` expression\nwith lock calls in any of the else blocks.", + "Why is this bad": "The Mutex lock remains held for the whole\n`if let ... else` block and deadlocks.", + "Known problems": "None.", + "Example": "```rust,ignore\nif let Ok(thing) = mutex.lock() {\n do_thing();\n} else {\n mutex.lock();\n}\n```\nShould be written\n```rust,ignore\nlet locked = mutex.lock();\nif let Ok(thing) = locked {\n do_thing(thing);\n} else {\n use_locked(locked);\n}\n```" + } + }, + { + "id": "if_let_redundant_pattern_matching", + "group": "deprecated", + "level": "Deprecated", + "docs": { + "What it does": "Nothing. This lint has been deprecated.", + "Deprecation reason": "The original rule will only lint for `if let`. After\nmaking it support to lint `match`, naming as `if let` is not suitable for it.\nSo, this lint is deprecated." + } + }, + { + "id": "if_let_some_result", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "* Checks for unnecessary `ok()` in if let.", + "Why is this bad": "Calling `ok()` in if let is unnecessary, instead match\non `Ok(pat)`", + "Known problems": "None.", + "Example": "```ignore\nfor i in iter {\n if let Some(value) = i.parse().ok() {\n vec.push(value)\n }\n}\n```\nCould be written:\n\n```ignore\nfor i in iter {\n if let Ok(value) = i.parse() {\n vec.push(value)\n }\n}\n```" + } + }, + { + "id": "if_not_else", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for usage of `!` or `!=` in an if condition with an\nelse branch.", + "Why is this bad": "Negations reduce the readability of statements.", + "Known problems": "None.", + "Example": "```rust\nif !v.is_empty() {\n a()\n} else {\n b()\n}\n```\n\nCould be written:\n\n```rust\nif v.is_empty() {\n b()\n} else {\n a()\n}\n```" + } + }, + { + "id": "if_same_then_else", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for `if/else` with the same body as the *then* part\nand the *else* part.", + "Why is this bad": "This is probably a copy & paste error.", + "Known problems": "Hopefully none.", + "Example": "```ignore\nlet foo = if \u2026 {\n 42\n} else {\n 42\n};\n```" + } + }, + { + "id": "ifs_same_cond", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for consecutive `if`s with the same condition.", + "Why is this bad": "This is probably a copy & paste error.", + "Known problems": "Hopefully none.", + "Example": "```ignore\nif a == b {\n \u2026\n} else if a == b {\n \u2026\n}\n```\n\nNote that this lint ignores all conditions with a function call as it could\nhave side effects:\n\n```ignore\nif foo() {\n \u2026\n} else if foo() { // not linted\n \u2026\n}\n```" + } + }, + { + "id": "implicit_hasher", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for public `impl` or `fn` missing generalization\nover different hashers and implicitly defaulting to the default hashing\nalgorithm (`SipHash`).", + "Why is this bad": "`HashMap` or `HashSet` with custom hashers cannot be\nused with them.", + "Known problems": "Suggestions for replacing constructors can contain\nfalse-positives. Also applying suggestions can require modification of other\npieces of code, possibly including external crates.", + "Example": "```rust\nimpl Serialize for HashMap { }\n\npub fn foo(map: &mut HashMap) { }\n```\ncould be rewritten as\n```rust\nimpl Serialize for HashMap { }\n\npub fn foo(map: &mut HashMap) { }\n```" + } + }, + { + "id": "implicit_return", + "group": "restriction", + "level": "Allow", + "docs": { + "What it does": "Checks for missing return statements at the end of a block.", + "Why is this bad": "Actually omitting the return keyword is idiomatic Rust code. Programmers\ncoming from other languages might prefer the expressiveness of `return`. It's possible to miss\nthe last returning statement because the only difference is a missing `;`. Especially in bigger\ncode with multiple return paths having a `return` keyword makes it easier to find the\ncorresponding statements.", + "Known problems": "None.", + "Example": "```rust\nfn foo(x: usize) -> usize {\n x\n}\n```\nadd return\n```rust\nfn foo(x: usize) -> usize {\n return x;\n}\n```" + } + }, + { + "id": "implicit_saturating_sub", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for implicit saturating subtraction.", + "Why is this bad": "Simplicity and readability. Instead we can easily use an builtin function.", + "Known problems": "None.", + "Example": "```rust\nlet end: u32 = 10;\nlet start: u32 = 5;\n\nlet mut i: u32 = end - start;\n\n// Bad\nif i != 0 {\n i -= 1;\n}\n\n// Good\ni = i.saturating_sub(1);\n```" + } + }, + { + "id": "imprecise_flops", + "group": "nursery", + "level": "Allow", + "docs": { + "What it does": "Looks for floating-point expressions that\ncan be expressed using built-in methods to improve accuracy\nat the cost of performance.", + "Why is this bad": "Negatively impacts accuracy.", + "Known problems": "None", + "Example": "```rust\nlet a = 3f32;\nlet _ = a.powf(1.0 / 3.0);\nlet _ = (1.0 + a).ln();\nlet _ = a.exp() - 1.0;\n```\n\nis better expressed as\n\n```rust\nlet a = 3f32;\nlet _ = a.cbrt();\nlet _ = a.ln_1p();\nlet _ = a.exp_m1();\n```" + } + }, + { + "id": "inconsistent_digit_grouping", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Warns if an integral or floating-point constant is\ngrouped inconsistently with underscores.", + "Why is this bad": "Readers may incorrectly interpret inconsistently\ngrouped digits.", + "Known problems": "None.", + "Example": "```rust\n// Bad\nlet x: u64 = 618_64_9189_73_511;\n\n// Good\nlet x: u64 = 61_864_918_973_511;\n```" + } + }, + { + "id": "indexing_slicing", + "group": "restriction", + "level": "Allow", + "docs": { + "What it does": "Checks for usage of indexing or slicing. Arrays are special cases, this lint\ndoes report on arrays if we can tell that slicing operations are in bounds and does not\nlint on constant `usize` indexing on arrays because that is handled by rustc's `const_err` lint.", + "Why is this bad": "Indexing and slicing can panic at runtime and there are\nsafe alternatives.", + "Known problems": "Hopefully none.", + "Example": "```rust,no_run\n// Vector\nlet x = vec![0; 5];\n\n// Bad\nx[2];\n&x[2..100];\n&x[2..];\n&x[..100];\n\n// Good\nx.get(2);\nx.get(2..100);\nx.get(2..);\nx.get(..100);\n\n// Array\nlet y = [0, 1, 2, 3];\n\n// Bad\n&y[10..100];\n&y[10..];\n&y[..100];\n\n// Good\n&y[2..];\n&y[..2];\n&y[0..3];\ny.get(10);\ny.get(10..100);\ny.get(10..);\ny.get(..100);\n```" + } + }, + { + "id": "ineffective_bit_mask", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for bit masks in comparisons which can be removed\nwithout changing the outcome. The basic structure can be seen in the\nfollowing table:\n\n|Comparison| Bit Op |Example |equals |\n|----------|---------|-----------|-------|\n|`>` / `<=`|`|` / `^`|`x | 2 > 3`|`x > 3`|\n|`<` / `>=`|`|` / `^`|`x ^ 1 < 4`|`x < 4`|", + "Why is this bad": "Not equally evil as [`bad_bit_mask`](#bad_bit_mask),\nbut still a bit misleading, because the bit mask is ineffective.", + "Known problems": "False negatives: This lint will only match instances\nwhere we have figured out the math (which is for a power-of-two compared\nvalue). This means things like `x | 1 >= 7` (which would be better written\nas `x >= 6`) will not be reported (but bit masks like this are fairly\nuncommon).", + "Example": "```rust\nif (x | 1 > 3) { }\n```" + } + }, + { + "id": "inefficient_to_string", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for usage of `.to_string()` on an `&&T` where\n`T` implements `ToString` directly (like `&&str` or `&&String`).", + "Why is this bad": "This bypasses the specialized implementation of\n`ToString` and instead goes through the more expensive string formatting\nfacilities.", + "Known problems": "None.", + "Example": "```rust\n// Generic implementation for `T: Display` is used (slow)\n[\"foo\", \"bar\"].iter().map(|s| s.to_string());\n\n// OK, the specialized impl is used\n[\"foo\", \"bar\"].iter().map(|&s| s.to_string());\n```" + } + }, + { + "id": "infallible_destructuring_match", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for matches being used to destructure a single-variant enum\nor tuple struct where a `let` will suffice.", + "Why is this bad": "Just readability \u2013 `let` doesn't nest, whereas a `match` does.", + "Known problems": "None.", + "Example": "```rust\nenum Wrapper {\n Data(i32),\n}\n\nlet wrapper = Wrapper::Data(42);\n\nlet data = match wrapper {\n Wrapper::Data(i) => i,\n};\n```\n\nThe correct use would be:\n```rust\nenum Wrapper {\n Data(i32),\n}\n\nlet wrapper = Wrapper::Data(42);\nlet Wrapper::Data(data) = wrapper;\n```" + } + }, + { + "id": "infinite_iter", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for iteration that is guaranteed to be infinite.", + "Why is this bad": "While there may be places where this is acceptable\n(e.g., in event streams), in most cases this is simply an error.", + "Known problems": "None.", + "Example": "```no_run\nuse std::iter;\n\niter::repeat(1_u8).collect::>();\n```" + } + }, + { + "id": "inherent_to_string", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for the definition of inherent methods with a signature of `to_string(&self) -> String`.", + "Why is this bad": "This method is also implicitly defined if a type implements the `Display` trait. As the functionality of `Display` is much more versatile, it should be preferred.", + "Known problems": "None", + " Example": "```rust\n// Bad\npub struct A;\n\nimpl A {\n pub fn to_string(&self) -> String {\n \"I am A\".to_string()\n }\n}\n```\n\n```rust\n// Good\nuse std::fmt;\n\npub struct A;\n\nimpl fmt::Display for A {\n fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n write!(f, \"I am A\")\n }\n}\n```" + } + }, + { + "id": "inherent_to_string_shadow_display", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for the definition of inherent methods with a signature of `to_string(&self) -> String` and if the type implementing this method also implements the `Display` trait.", + "Why is this bad": "This method is also implicitly defined if a type implements the `Display` trait. The less versatile inherent method will then shadow the implementation introduced by `Display`.", + "Known problems": "None", + " Example": "```rust\n// Bad\nuse std::fmt;\n\npub struct A;\n\nimpl A {\n pub fn to_string(&self) -> String {\n \"I am A\".to_string()\n }\n}\n\nimpl fmt::Display for A {\n fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n write!(f, \"I am A, too\")\n }\n}\n```\n\n```rust\n// Good\nuse std::fmt;\n\npub struct A;\n\nimpl fmt::Display for A {\n fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n write!(f, \"I am A\")\n }\n}\n```" + } + }, + { + "id": "inline_always", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for items annotated with `#[inline(always)]`,\nunless the annotated function is empty or simply panics.", + "Why is this bad": "While there are valid uses of this annotation (and once\nyou know when to use it, by all means `allow` this lint), it's a common\nnewbie-mistake to pepper one's code with it.\n\nAs a rule of thumb, before slapping `#[inline(always)]` on a function,\nmeasure if that additional function call really affects your runtime profile\nsufficiently to make up for the increase in compile time.", + "Known problems": "False positives, big time. This lint is meant to be\ndeactivated by everyone doing serious performance work. This means having\ndone the measurement.", + "Example": "```ignore\n#[inline(always)]\nfn not_quite_hot_code(..) { ... }\n```" + } + }, + { + "id": "inline_fn_without_body", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for `#[inline]` on trait methods without bodies", + "Why is this bad": "Only implementations of trait methods may be inlined.\nThe inline attribute is ignored for trait methods without bodies.", + "Known problems": "None.", + "Example": "```rust\ntrait Animal {\n #[inline]\n fn name(&self) -> &'static str;\n}\n```" + } + }, + { + "id": "int_plus_one", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for usage of `x >= y + 1` or `x - 1 >= y` (and `<=`) in a block", + "Why is this bad": "Readability -- better to use `> y` instead of `>= y + 1`.", + "Known problems": "None.", + "Example": "```rust\nif x >= y + 1 {}\n```\n\nCould be written as:\n\n```rust\nif x > y {}\n```" + } + }, + { + "id": "integer_arithmetic", + "group": "restriction", + "level": "Allow", + "docs": { + "What it does": "Checks for integer arithmetic operations which could overflow or panic.\n\nSpecifically, checks for any operators (`+`, `-`, `*`, `<<`, etc) which are capable\nof overflowing according to the [Rust\nReference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#overflow),\nor which can panic (`/`, `%`). No bounds analysis or sophisticated reasoning is\nattempted.", + "Why is this bad": "Integer overflow will trigger a panic in debug builds or will wrap in\nrelease mode. Division by zero will cause a panic in either mode. In some applications one\nwants explicitly checked, wrapping or saturating arithmetic.", + "Known problems": "None.", + "Example": "```rust\na + 1;\n```" + } + }, + { + "id": "integer_division", + "group": "restriction", + "level": "Allow", + "docs": { + "What it does": "Checks for division of integers", + "Why is this bad": "When outside of some very specific algorithms,\ninteger division is very often a mistake because it discards the\nremainder.", + "Known problems": "None.", + "Example": "```rust\n// Bad\nlet x = 3 / 2;\nprintln!(\"{}\", x);\n\n// Good\nlet x = 3f32 / 2f32;\nprintln!(\"{}\", x);\n```" + } + }, + { + "id": "into_iter_on_array", + "group": "deprecated", + "level": "Deprecated", + "docs": { + "What it does": "Nothing. This lint has been deprecated.", + "Deprecation reason": "This lint has been uplifted to rustc and is now called\n`array_into_iter`." + } + }, + { + "id": "into_iter_on_ref", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for `into_iter` calls on references which should be replaced by `iter`\nor `iter_mut`.", + "Why is this bad": "Readability. Calling `into_iter` on a reference will not move out its\ncontent into the resulting iterator, which is confusing. It is better just call `iter` or\n`iter_mut` directly.", + "Known problems": "None", + "Example": "```rust\n// Bad\nlet _ = (&vec![3, 4, 5]).into_iter();\n\n// Good\nlet _ = (&vec![3, 4, 5]).iter();\n```" + } + }, + { + "id": "invalid_atomic_ordering", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for usage of invalid atomic\nordering in atomic loads/stores and memory fences.", + "Why is this bad": "Using an invalid atomic ordering\nwill cause a panic at run-time.", + "Known problems": "None.", + "Example": "```rust,no_run\n\nlet x = AtomicBool::new(true);\n\nlet _ = x.load(Ordering::Release);\nlet _ = x.load(Ordering::AcqRel);\n\nx.store(false, Ordering::Acquire);\nx.store(false, Ordering::AcqRel);\n\natomic::fence(Ordering::Relaxed);\natomic::compiler_fence(Ordering::Relaxed);\n```" + } + }, + { + "id": "invalid_ref", + "group": "deprecated", + "level": "Deprecated", + "docs": { + "What it does": "Nothing. This lint has been deprecated.", + "Deprecation reason": "This lint has been superseded by the warn-by-default\n`invalid_value` rustc lint." + } + }, + { + "id": "invalid_regex", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks [regex](https://crates.io/crates/regex) creation\n(with `Regex::new`,`RegexBuilder::new` or `RegexSet::new`) for correct\nregex syntax.", + "Why is this bad": "This will lead to a runtime panic.", + "Known problems": "None.", + "Example": "```ignore\nRegex::new(\"|\")\n```" + } + }, + { + "id": "invalid_upcast_comparisons", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for comparisons where the relation is always either\ntrue or false, but where one side has been upcast so that the comparison is\nnecessary. Only integer types are checked.", + "Why is this bad": "An expression like `let x : u8 = ...; (x as u32) > 300`\nwill mistakenly imply that it is possible for `x` to be outside the range of\n`u8`.", + "Known problems": "https://github.com/rust-lang/rust-clippy/issues/886", + "Example": "```rust\nlet x: u8 = 1;\n(x as u32) > 300;\n```" + } + }, + { + "id": "items_after_statements", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for items declared after some statement in a block.", + "Why is this bad": "Items live for the entire scope they are declared\nin. But statements are processed in order. This might cause confusion as\nit's hard to figure out which item is meant in a statement.", + "Known problems": "None.", + "Example": "```rust\n// Bad\nfn foo() {\n println!(\"cake\");\n}\n\nfn main() {\n foo(); // prints \"foo\"\n fn foo() {\n println!(\"foo\");\n }\n foo(); // prints \"foo\"\n}\n```\n\n```rust\n// Good\nfn foo() {\n println!(\"cake\");\n}\n\nfn main() {\n fn foo() {\n println!(\"foo\");\n }\n foo(); // prints \"foo\"\n foo(); // prints \"foo\"\n}\n```" + } + }, + { + "id": "iter_cloned_collect", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for the use of `.cloned().collect()` on slice to\ncreate a `Vec`.", + "Why is this bad": "`.to_vec()` is clearer", + "Known problems": "None.", + "Example": "```rust\nlet s = [1, 2, 3, 4, 5];\nlet s2: Vec = s[..].iter().cloned().collect();\n```\nThe better use would be:\n```rust\nlet s = [1, 2, 3, 4, 5];\nlet s2: Vec = s.to_vec();\n```" + } + }, + { + "id": "iter_next_loop", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for loops on `x.next()`.", + "Why is this bad": "`next()` returns either `Some(value)` if there was a\nvalue, or `None` otherwise. The insidious thing is that `Option<_>`\nimplements `IntoIterator`, so that possibly one value will be iterated,\nleading to some hard to find bugs. No one will want to write such code\n[except to win an Underhanded Rust\nContest](https://www.reddit.com/r/rust/comments/3hb0wm/underhanded_rust_contest/cu5yuhr).", + "Known problems": "None.", + "Example": "```ignore\nfor x in y.next() {\n ..\n}\n```" + } + }, + { + "id": "iter_next_slice", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for usage of `iter().next()` on a Slice or an Array", + "Why is this bad": "These can be shortened into `.get()`", + "Known problems": "None.", + "Example": "```rust\na[2..].iter().next();\nb.iter().next();\n```\nshould be written as:\n```rust\na.get(2);\nb.get(0);\n```" + } + }, + { + "id": "iter_nth", + "group": "perf", + "level": "Warn", + "docs": { + "What it does": "Checks for use of `.iter().nth()` (and the related\n`.iter_mut().nth()`) on standard library types with O(1) element access.", + "Why is this bad": "`.get()` and `.get_mut()` are more efficient and more\nreadable.", + "Known problems": "None.", + "Example": "```rust\nlet some_vec = vec![0, 1, 2, 3];\nlet bad_vec = some_vec.iter().nth(3);\nlet bad_slice = &some_vec[..].iter().nth(3);\n```\nThe correct use would be:\n```rust\nlet some_vec = vec![0, 1, 2, 3];\nlet bad_vec = some_vec.get(3);\nlet bad_slice = &some_vec[..].get(3);\n```" + } + }, + { + "id": "iter_nth_zero", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for the use of `iter.nth(0)`.", + "Why is this bad": "`iter.next()` is equivalent to\n`iter.nth(0)`, as they both consume the next element,\n but is more readable.", + "Known problems": "None.", + "Example": "```rust\n// Bad\nlet x = s.iter().nth(0);\n\n// Good\nlet x = s.iter().next();\n```" + } + }, + { + "id": "iter_skip_next", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for use of `.skip(x).next()` on iterators.", + "Why is this bad": "`.nth(x)` is cleaner", + "Known problems": "None.", + "Example": "```rust\nlet some_vec = vec![0, 1, 2, 3];\nlet bad_vec = some_vec.iter().skip(3).next();\nlet bad_slice = &some_vec[..].iter().skip(3).next();\n```\nThe correct use would be:\n```rust\nlet some_vec = vec![0, 1, 2, 3];\nlet bad_vec = some_vec.iter().nth(3);\nlet bad_slice = &some_vec[..].iter().nth(3);\n```" + } + }, + { + "id": "iterator_step_by_zero", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for calling `.step_by(0)` on iterators which panics.", + "Why is this bad": "This very much looks like an oversight. Use `panic!()` instead if you\nactually intend to panic.", + "Known problems": "None.", + "Example": "```rust,should_panic\nfor x in (0..100).step_by(0) {\n //..\n}\n```" + } + }, + { + "id": "just_underscores_and_digits", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks if you have variables whose name consists of just\nunderscores and digits.", + "Why is this bad": "It's hard to memorize what a variable means without a\ndescriptive name.", + "Known problems": "None?", + "Example": "```rust\nlet _1 = 1;\nlet ___1 = 1;\nlet __1___2 = 11;\n```" + } + }, + { + "id": "large_const_arrays", + "group": "perf", + "level": "Warn", + "docs": { + "What it does": "Checks for large `const` arrays that should\nbe defined as `static` instead.", + "Why is this bad": "Performance: const variables are inlined upon use.\nStatic items result in only one instance and has a fixed location in memory.", + "Known problems": "None.", + "Example": "```rust,ignore\n// Bad\npub const a = [0u32; 1_000_000];\n\n// Good\npub static a = [0u32; 1_000_000];\n```", + "Configuration": "This lint has the following configuration variables:\n\n* `array-size-threshold: u64`: The maximum allowed size for arrays on the stack (defaults to `512_000`)." + } + }, + { + "id": "large_digit_groups", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Warns if the digits of an integral or floating-point\nconstant are grouped into groups that\nare too large.", + "Why is this bad": "Negatively impacts readability.", + "Known problems": "None.", + "Example": "```rust\nlet x: u64 = 6186491_8973511;\n```" + } + }, + { + "id": "large_enum_variant", + "group": "perf", + "level": "Warn", + "docs": { + "What it does": "Checks for large size differences between variants on\n`enum`s.", + "Why is this bad": "Enum size is bounded by the largest variant. Having a\nlarge variant can penalize the memory layout of that enum.", + "Known problems": "This lint obviously cannot take the distribution of\nvariants in your running program into account. It is possible that the\nsmaller variants make up less than 1% of all instances, in which case\nthe overhead is negligible and the boxing is counter-productive. Always\nmeasure the change this lint suggests.", + "Example": "```rust\n// Bad\nenum Test {\n A(i32),\n B([i32; 8000]),\n}\n\n// Possibly better\nenum Test2 {\n A(i32),\n B(Box<[i32; 8000]>),\n}\n```", + "Configuration": "This lint has the following configuration variables:\n\n* `enum-variant-size-threshold: u64`: The maximum size of a enum's variant to avoid box suggestion (defaults to `200`)." + } + }, + { + "id": "large_stack_arrays", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for local arrays that may be too large.", + "Why is this bad": "Large local arrays may cause stack overflow.", + "Known problems": "None.", + "Example": "```rust,ignore\nlet a = [0u32; 1_000_000];\n```", + "Configuration": "This lint has the following configuration variables:\n\n* `array-size-threshold: u64`: The maximum allowed size for arrays on the stack (defaults to `512_000`)." + } + }, + { + "id": "len_without_is_empty", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for items that implement `.len()` but not\n`.is_empty()`.", + "Why is this bad": "It is good custom to have both methods, because for\nsome data structures, asking about the length will be a costly operation,\nwhereas `.is_empty()` can usually answer in constant time. Also it used to\nlead to false positives on the [`len_zero`](#len_zero) lint \u2013 currently that\nlint will ignore such entities.", + "Known problems": "None.", + "Example": "```ignore\nimpl X {\n pub fn len(&self) -> usize {\n ..\n }\n}\n```" + } + }, + { + "id": "len_zero", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for getting the length of something via `.len()`\njust to compare to zero, and suggests using `.is_empty()` where applicable.", + "Why is this bad": "Some structures can answer `.is_empty()` much faster\nthan calculating their length. So it is good to get into the habit of using\n`.is_empty()`, and having it is cheap.\nBesides, it makes the intent clearer than a manual comparison in some contexts.", + "Known problems": "None.", + "Example": "```ignore\nif x.len() == 0 {\n ..\n}\nif y.len() != 0 {\n ..\n}\n```\ninstead use\n```ignore\nif x.is_empty() {\n ..\n}\nif !y.is_empty() {\n ..\n}\n```" + } + }, + { + "id": "let_and_return", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for `let`-bindings, which are subsequently\nreturned.", + "Why is this bad": "It is just extraneous code. Remove it to make your code\nmore rusty.", + "Known problems": "None.", + "Example": "```rust\nfn foo() -> String {\n let x = String::new();\n x\n}\n```\ninstead, use\n```\nfn foo() -> String {\n String::new()\n}\n```" + } + }, + { + "id": "let_underscore_lock", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for `let _ = sync_lock`", + "Why is this bad": "This statement immediately drops the lock instead of\nextending its lifetime to the end of the scope, which is often not intended.\nTo extend lock lifetime to the end of the scope, use an underscore-prefixed\nname instead (i.e. _lock). If you want to explicitly drop the lock,\n`std::mem::drop` conveys your intention better and is less error-prone.", + "Known problems": "None.", + "Example": "Bad:\n```rust,ignore\nlet _ = mutex.lock();\n```\n\nGood:\n```rust,ignore\nlet _lock = mutex.lock();\n```" + } + }, + { + "id": "let_underscore_must_use", + "group": "restriction", + "level": "Allow", + "docs": { + "What it does": "Checks for `let _ = `\nwhere expr is #[must_use]", + "Why is this bad": "It's better to explicitly\nhandle the value of a #[must_use] expr", + "Known problems": "None.", + "Example": "```rust\nfn f() -> Result {\n Ok(0)\n}\n\nlet _ = f();\n// is_ok() is marked #[must_use]\nlet _ = f().is_ok();\n```" + } + }, + { + "id": "let_unit_value", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for binding a unit value.", + "Why is this bad": "A unit value cannot usefully be used anywhere. So\nbinding one is kind of pointless.", + "Known problems": "None.", + "Example": "```rust\nlet x = {\n 1;\n};\n```" + } + }, + { + "id": "linkedlist", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for usage of any `LinkedList`, suggesting to use a\n`Vec` or a `VecDeque` (formerly called `RingBuf`).", + "Why is this bad": "Gankro says:\n\n> The TL;DR of `LinkedList` is that it's built on a massive amount of\npointers and indirection.\n> It wastes memory, it has terrible cache locality, and is all-around slow.\n`RingBuf`, while\n> \"only\" amortized for push/pop, should be faster in the general case for\nalmost every possible\n> workload, and isn't even amortized at all if you can predict the capacity\nyou need.\n>\n> `LinkedList`s are only really good if you're doing a lot of merging or\nsplitting of lists.\n> This is because they can just mangle some pointers instead of actually\ncopying the data. Even\n> if you're doing a lot of insertion in the middle of the list, `RingBuf`\ncan still be better\n> because of how expensive it is to seek to the middle of a `LinkedList`.", + "Known problems": "False positives \u2013 the instances where using a\n`LinkedList` makes sense are few and far between, but they can still happen.", + "Example": "```rust\nlet x: LinkedList = LinkedList::new();\n```" + } + }, + { + "id": "logic_bug", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for boolean expressions that contain terminals that\ncan be eliminated.", + "Why is this bad": "This is most likely a logic bug.", + "Known problems": "Ignores short circuiting behavior.", + "Example": "```ignore\nif a && b || a { ... }\n```\nThe `b` is unnecessary, the expression is equivalent to `if a`." + } + }, + { + "id": "lossy_float_literal", + "group": "restriction", + "level": "Allow", + "docs": { + "What it does": "Checks for whole number float literals that\ncannot be represented as the underlying type without loss.", + "Why is this bad": "Rust will silently lose precision during\nconversion to a float.", + "Known problems": "None.", + "Example": "```rust\n// Bad\nlet _: f32 = 16_777_217.0; // 16_777_216.0\n\n// Good\nlet _: f32 = 16_777_216.0;\nlet _: f64 = 16_777_217.0;\n```" + } + }, + { + "id": "macro_use_imports", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for `#[macro_use] use...`.", + "Why is this bad": "Since the Rust 2018 edition you can import\nmacro's directly, this is considered idiomatic.", + "Known problems": "None.", + "Example": "```rust\n#[macro_use]\nuse lazy_static;\n```" + } + }, + { + "id": "main_recursion", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for recursion using the entrypoint.", + "Why is this bad": "Apart from special setups (which we could detect following attributes like #![no_std]),\nrecursing into main() seems like an unintuitive antipattern we should be able to detect.", + "Known problems": "None.", + "Example": "```no_run\nfn main() {\n main();\n}\n```" + } + }, + { + "id": "manual_async_fn", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "It checks for manual implementations of `async` functions.", + "Why is this bad": "It's more idiomatic to use the dedicated syntax.", + "Known problems": "None.", + "Example": "```rust\nuse std::future::Future;\n\nfn foo() -> impl Future { async { 42 } }\n```\nUse instead:\n```rust\nuse std::future::Future;\n\nasync fn foo() -> i32 { 42 }\n```" + } + }, + { + "id": "manual_memcpy", + "group": "perf", + "level": "Warn", + "docs": { + "What it does": "Checks for for-loops that manually copy items between\nslices that could be optimized by having a memcpy.", + "Why is this bad": "It is not as fast as a memcpy.", + "Known problems": "None.", + "Example": "```rust\nfor i in 0..src.len() {\n dst[i + 64] = src[i];\n}\n```\nCould be written as:\n```rust\ndst[64..(src.len() + 64)].clone_from_slice(&src[..]);\n```" + } + }, + { + "id": "manual_non_exhaustive", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for manual implementations of the non-exhaustive pattern.", + "Why is this bad": "Using the #[non_exhaustive] attribute expresses better the intent\nand allows possible optimizations when applied to enums.", + "Known problems": "None.", + "Example": "```rust\nstruct S {\n pub a: i32,\n pub b: i32,\n _c: (),\n}\n\nenum E {\n A,\n B,\n #[doc(hidden)]\n _C,\n}\n\nstruct T(pub i32, pub i32, ());\n```\nUse instead:\n```rust\n#[non_exhaustive]\nstruct S {\n pub a: i32,\n pub b: i32,\n}\n\n#[non_exhaustive]\nenum E {\n A,\n B,\n}\n\n#[non_exhaustive]\nstruct T(pub i32, pub i32);\n```" + } + }, + { + "id": "manual_saturating_arithmetic", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for `.checked_add/sub(x).unwrap_or(MAX/MIN)`.", + "Why is this bad": "These can be written simply with `saturating_add/sub` methods.", + "Example": "```rust\nlet add = x.checked_add(y).unwrap_or(u32::MAX);\nlet sub = x.checked_sub(y).unwrap_or(u32::MIN);\n```\n\ncan be written using dedicated methods for saturating addition/subtraction as:\n\n```rust\nlet add = x.saturating_add(y);\nlet sub = x.saturating_sub(y);\n```" + } + }, + { + "id": "manual_swap", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for manual swapping.", + "Why is this bad": "The `std::mem::swap` function exposes the intent better\nwithout deinitializing or copying either variable.", + "Known problems": "None.", + "Example": "```rust\nlet mut a = 42;\nlet mut b = 1337;\n\nlet t = b;\nb = a;\na = t;\n```\nUse std::mem::swap():\n```rust\nlet mut a = 1;\nlet mut b = 2;\nstd::mem::swap(&mut a, &mut b);\n```" + } + }, + { + "id": "many_single_char_names", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for too many variables whose name consists of a\nsingle character.", + "Why is this bad": "It's hard to memorize what a variable means without a\ndescriptive name.", + "Known problems": "None?", + "Example": "```ignore\nlet (a, b, c, d, e, f, g) = (...);\n```", + "Configuration": "This lint has the following configuration variables:\n\n* `single-char-binding-names-threshold: u64`: The maximum number of single char bindings a scope may have (defaults to `4`)." + } + }, + { + "id": "map_clone", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for usage of `iterator.map(|x| x.clone())` and suggests\n`iterator.cloned()` instead", + "Why is this bad": "Readability, this can be written more concisely", + "Known problems": "None", + "Example": "```rust\nlet x = vec![42, 43];\nlet y = x.iter();\nlet z = y.map(|i| *i);\n```\n\nThe correct use would be:\n\n```rust\nlet x = vec![42, 43];\nlet y = x.iter();\nlet z = y.cloned();\n```" + } + }, + { + "id": "map_entry", + "group": "perf", + "level": "Warn", + "docs": { + "What it does": "Checks for uses of `contains_key` + `insert` on `HashMap`\nor `BTreeMap`.", + "Why is this bad": "Using `entry` is more efficient.", + "Known problems": "Some false negatives, eg.:\n```rust\nif !map.contains_key(&k) {\n map.insert(k.clone(), v);\n}\n```", + "Example": "```rust\nif !map.contains_key(&k) {\n map.insert(k, v);\n}\n```\ncan both be rewritten as:\n```rust\nmap.entry(k).or_insert(v);\n```" + } + }, + { + "id": "map_flatten", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for usage of `_.map(_).flatten(_)`,", + "Why is this bad": "Readability, this can be written more concisely as a\nsingle method call using `_.flat_map(_)`", + "Known problems": "", + "Example": "```rust\nlet vec = vec![vec![1]];\n\n// Bad\nvec.iter().map(|x| x.iter()).flatten();\n\n// Good\nvec.iter().flat_map(|x| x.iter());\n```" + } + }, + { + "id": "map_unwrap_or", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for usage of `option.map(_).unwrap_or(_)` or `option.map(_).unwrap_or_else(_)` or\n`result.map(_).unwrap_or_else(_)`.", + "Why is this bad": "Readability, these can be written more concisely (resp.) as\n`option.map_or(_, _)`, `option.map_or_else(_, _)` and `result.map_or_else(_, _)`.", + "Known problems": "The order of the arguments is not in execution order", + "Examples": "```rust\n\n// Bad\nx.map(|a| a + 1).unwrap_or(0);\n\n// Good\nx.map_or(0, |a| a + 1);\n```\n\n// or\n\n```rust\n\n// Bad\nx.map(|a| a + 1).unwrap_or_else(some_function);\n\n// Good\nx.map_or_else(some_function, |a| a + 1);\n```" + } + }, + { + "id": "match_as_ref", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for match which is used to add a reference to an\n`Option` value.", + "Why is this bad": "Using `as_ref()` or `as_mut()` instead is shorter.", + "Known problems": "None.", + "Example": "```rust\nlet x: Option<()> = None;\n\n// Bad\nlet r: Option<&()> = match x {\n None => None,\n Some(ref v) => Some(v),\n};\n\n// Good\nlet r: Option<&()> = x.as_ref();\n```" + } + }, + { + "id": "match_bool", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for matches where match expression is a `bool`. It\nsuggests to replace the expression with an `if...else` block.", + "Why is this bad": "It makes the code less readable.", + "Known problems": "None.", + "Example": "```rust\nlet condition: bool = true;\nmatch condition {\n true => foo(),\n false => bar(),\n}\n```\nUse if/else instead:\n```rust\nlet condition: bool = true;\nif condition {\n foo();\n} else {\n bar();\n}\n```" + } + }, + { + "id": "match_on_vec_items", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for `match vec[idx]` or `match vec[n..m]`.", + "Why is this bad": "This can panic at runtime.", + "Known problems": "None.", + "Example": "```rust, no_run\nlet arr = vec![0, 1, 2, 3];\nlet idx = 1;\n\n// Bad\nmatch arr[idx] {\n 0 => println!(\"{}\", 0),\n 1 => println!(\"{}\", 3),\n _ => {},\n}\n```\nUse instead:\n```rust, no_run\nlet arr = vec![0, 1, 2, 3];\nlet idx = 1;\n\n// Good\nmatch arr.get(idx) {\n Some(0) => println!(\"{}\", 0),\n Some(1) => println!(\"{}\", 3),\n _ => {},\n}\n```" + } + }, + { + "id": "match_overlapping_arm", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for overlapping match arms.", + "Why is this bad": "It is likely to be an error and if not, makes the code\nless obvious.", + "Known problems": "None.", + "Example": "```rust\nlet x = 5;\nmatch x {\n 1...10 => println!(\"1 ... 10\"),\n 5...15 => println!(\"5 ... 15\"),\n _ => (),\n}\n```" + } + }, + { + "id": "match_ref_pats", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for matches where all arms match a reference,\nsuggesting to remove the reference and deref the matched expression\ninstead. It also checks for `if let &foo = bar` blocks.", + "Why is this bad": "It just makes the code less readable. That reference\ndestructuring adds nothing to the code.", + "Known problems": "None.", + "Example": "```rust,ignore\n// Bad\nmatch x {\n &A(ref y) => foo(y),\n &B => bar(),\n _ => frob(&x),\n}\n\n// Good\nmatch *x {\n A(ref y) => foo(y),\n B => bar(),\n _ => frob(x),\n}\n```" + } + }, + { + "id": "match_same_arms", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for `match` with identical arm bodies.", + "Why is this bad": "This is probably a copy & paste error. If arm bodies\nare the same on purpose, you can factor them\n[using `|`](https://doc.rust-lang.org/book/patterns.html#multiple-patterns).", + "Known problems": "False positive possible with order dependent `match`\n(see issue\n[#860](https://github.com/rust-lang/rust-clippy/issues/860)).", + "Example": "```rust,ignore\nmatch foo {\n Bar => bar(),\n Quz => quz(),\n Baz => bar(), // <= oops\n}\n```\n\nThis should probably be\n```rust,ignore\nmatch foo {\n Bar => bar(),\n Quz => quz(),\n Baz => baz(), // <= fixed\n}\n```\n\nor if the original code was not a typo:\n```rust,ignore\nmatch foo {\n Bar | Baz => bar(), // <= shows the intent better\n Quz => quz(),\n}\n```" + } + }, + { + "id": "match_single_binding", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for useless match that binds to only one value.", + "Why is this bad": "Readability and needless complexity.", + "Known problems": "Suggested replacements may be incorrect when `match`\nis actually binding temporary value, bringing a 'dropped while borrowed' error.", + "Example": "```rust\n\n// Bad\nmatch (a, b) {\n (c, d) => {\n // useless match\n }\n}\n\n// Good\nlet (c, d) = (a, b);\n```" + } + }, + { + "id": "match_wild_err_arm", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for arm which matches all errors with `Err(_)`\nand take drastic actions like `panic!`.", + "Why is this bad": "It is generally a bad practice, similar to\ncatching all exceptions in java with `catch(Exception)`", + "Known problems": "None.", + "Example": "```rust\nlet x: Result = Ok(3);\nmatch x {\n Ok(_) => println!(\"ok\"),\n Err(_) => panic!(\"err\"),\n}\n```" + } + }, + { + "id": "match_wildcard_for_single_variants", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for wildcard enum matches for a single variant.", + "Why is this bad": "New enum variants added by library updates can be missed.", + "Known problems": "Suggested replacements may not use correct path to enum\nif it's not present in the current scope.", + "Example": "```rust\n// Bad\nmatch x {\n Foo::A => {},\n Foo::B => {},\n _ => {},\n}\n\n// Good\nmatch x {\n Foo::A => {},\n Foo::B => {},\n Foo::C => {},\n}\n```" + } + }, + { + "id": "maybe_infinite_iter", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for iteration that may be infinite.", + "Why is this bad": "While there may be places where this is acceptable\n(e.g., in event streams), in most cases this is simply an error.", + "Known problems": "The code may have a condition to stop iteration, but\nthis lint is not clever enough to analyze it.", + "Example": "```rust\nlet infinite_iter = 0..;\n[0..].iter().zip(infinite_iter.take_while(|x| *x > 5));\n```" + } + }, + { + "id": "mem_discriminant_non_enum", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for calls of `mem::discriminant()` on a non-enum type.", + "Why is this bad": "The value of `mem::discriminant()` on non-enum types\nis unspecified.", + "Known problems": "None.", + "Example": "```rust\nuse std::mem;\n\nmem::discriminant(&\"hello\");\nmem::discriminant(&&Some(2));\n```" + } + }, + { + "id": "mem_forget", + "group": "restriction", + "level": "Allow", + "docs": { + "What it does": "Checks for usage of `std::mem::forget(t)` where `t` is\n`Drop`.", + "Why is this bad": "`std::mem::forget(t)` prevents `t` from running its\ndestructor, possibly causing leaks.", + "Known problems": "None.", + "Example": "```rust\nmem::forget(Rc::new(55))\n```" + } + }, + { + "id": "mem_replace_option_with_none", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for `mem::replace()` on an `Option` with\n`None`.", + "Why is this bad": "`Option` already has the method `take()` for\ntaking its current value (Some(..) or None) and replacing it with\n`None`.", + "Known problems": "None.", + "Example": "```rust\nuse std::mem;\n\nlet mut an_option = Some(0);\nlet replaced = mem::replace(&mut an_option, None);\n```\nIs better expressed with:\n```rust\nlet mut an_option = Some(0);\nlet taken = an_option.take();\n```" + } + }, + { + "id": "mem_replace_with_default", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for `std::mem::replace` on a value of type\n`T` with `T::default()`.", + "Why is this bad": "`std::mem` module already has the method `take` to\ntake the current value and replace it with the default value of that type.", + "Known problems": "None.", + "Example": "```rust\nlet mut text = String::from(\"foo\");\nlet replaced = std::mem::replace(&mut text, String::default());\n```\nIs better expressed with:\n```rust\nlet mut text = String::from(\"foo\");\nlet taken = std::mem::take(&mut text);\n```" + } + }, + { + "id": "mem_replace_with_uninit", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for `mem::replace(&mut _, mem::uninitialized())`\nand `mem::replace(&mut _, mem::zeroed())`.", + "Why is this bad": "This will lead to undefined behavior even if the\nvalue is overwritten later, because the uninitialized value may be\nobserved in the case of a panic.", + "Known problems": "None.", + "Example": "```\nuse std::mem;\n# fn may_panic(v: Vec) -> Vec { v }\n\n#[allow(deprecated, invalid_value)]\nfn myfunc (v: &mut Vec) {\n let taken_v = unsafe { mem::replace(v, mem::uninitialized()) };\n let new_v = may_panic(taken_v); // undefined behavior on panic\n mem::forget(mem::replace(v, new_v));\n}\n```\n\nThe [take_mut](https://docs.rs/take_mut) crate offers a sound solution,\nat the cost of either lazily creating a replacement value or aborting\non panic, to ensure that the uninitialized value cannot be observed." + } + }, + { + "id": "min_max", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for expressions where `std::cmp::min` and `max` are\nused to clamp values, but switched so that the result is constant.", + "Why is this bad": "This is in all probability not the intended outcome. At\nthe least it hurts readability of the code.", + "Known problems": "None", + "Example": "```ignore\nmin(0, max(100, x))\n```\nIt will always be equal to `0`. Probably the author meant to clamp the value\nbetween 0 and 100, but has erroneously swapped `min` and `max`." + } + }, + { + "id": "misaligned_transmute", + "group": "deprecated", + "level": "Deprecated", + "docs": { + "What it does": "Nothing. This lint has been deprecated.", + "Deprecation reason": "This lint should never have applied to non-pointer types, as transmuting\nbetween non-pointer types of differing alignment is well-defined behavior (it's semantically\nequivalent to a memcpy). This lint has thus been refactored into two separate lints:\ncast_ptr_alignment and transmute_ptr_to_ptr." + } + }, + { + "id": "mismatched_target_os", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for cfg attributes having operating systems used in target family position.", + "Why is this bad": "The configuration option will not be recognised and the related item will not be included\nby the conditional compilation engine.", + "Known problems": "None.", + "Example": "Bad:\n```rust\n#[cfg(linux)]\nfn conditional() { }\n```\n\nGood:\n```rust\n#[cfg(target_os = \"linux\")]\nfn conditional() { }\n```\n\nOr:\n```rust\n#[cfg(unix)]\nfn conditional() { }\n```\nCheck the [Rust Reference](https://doc.rust-lang.org/reference/conditional-compilation.html#target_os) for more details." + } + }, + { + "id": "misrefactored_assign_op", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for `a op= a op b` or `a op= b op a` patterns.", + "Why is this bad": "Most likely these are bugs where one meant to write `a\nop= b`.", + "Known problems": "Clippy cannot know for sure if `a op= a op b` should have\nbeen `a = a op a op b` or `a = a op b`/`a op= b`. Therefore, it suggests both.\nIf `a op= a op b` is really the correct behaviour it should be\nwritten as `a = a op a op b` as it's less confusing.", + "Example": "```rust\nlet mut a = 5;\nlet b = 2;\n// ...\na += a + b;\n```" + } + }, + { + "id": "missing_const_for_fn", + "group": "nursery", + "level": "Allow", + "docs": { + "What it does": "Suggests the use of `const` in functions and methods where possible.", + "Why is this bad": "Not having the function const prevents callers of the function from being const as well.", + "Known problems": "Const functions are currently still being worked on, with some features only being available\non nightly. This lint does not consider all edge cases currently and the suggestions may be\nincorrect if you are using this lint on stable.\n\nAlso, the lint only runs one pass over the code. Consider these two non-const functions:\n\n```rust\nfn a() -> i32 {\n 0\n}\nfn b() -> i32 {\n a()\n}\n```\n\nWhen running Clippy, the lint will only suggest to make `a` const, because `b` at this time\ncan't be const as it calls a non-const function. Making `a` const and running Clippy again,\nwill suggest to make `b` const, too.", + "Example": "```rust\nfn new() -> Self {\n Self { random_number: 42 }\n}\n```\n\nCould be a const fn:\n\n```rust\nconst fn new() -> Self {\n Self { random_number: 42 }\n}\n```" + } + }, + { + "id": "missing_docs_in_private_items", + "group": "restriction", + "level": "Allow", + "docs": { + "What it does": "Warns if there is missing doc for any documentable item\n(public or private).", + "Why is this bad": "Doc is good. *rustc* has a `MISSING_DOCS`\nallowed-by-default lint for\npublic members, but has no way to enforce documentation of private items.\nThis lint fixes that.", + "Known problems": "None." + } + }, + { + "id": "missing_errors_doc", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks the doc comments of publicly visible functions that\nreturn a `Result` type and warns if there is no `# Errors` section.", + "Why is this bad": "Documenting the type of errors that can be returned from a\nfunction can help callers write code to handle the errors appropriately.", + "Known problems": "None.", + "Examples": "Since the following function returns a `Result` it has an `# Errors` section in\nits doc comment:\n\n```rust\n/// # Errors\n///\n/// Will return `Err` if `filename` does not exist or the user does not have\n/// permission to read it.\npub fn read(filename: String) -> io::Result {\n unimplemented!();\n}\n```" + } + }, + { + "id": "missing_inline_in_public_items", + "group": "restriction", + "level": "Allow", + "docs": { + "What it does": "it lints if an exported function, method, trait method with default impl,\nor trait method impl is not `#[inline]`.", + "Why is this bad": "In general, it is not. Functions can be inlined across\ncrates when that's profitable as long as any form of LTO is used. When LTO is disabled,\nfunctions that are not `#[inline]` cannot be inlined across crates. Certain types of crates\nmight intend for most of the methods in their public API to be able to be inlined across\ncrates even when LTO is disabled. For these types of crates, enabling this lint might make\nsense. It allows the crate to require all exported methods to be `#[inline]` by default, and\nthen opt out for specific methods where this might not make sense.", + "Known problems": "None.", + "Example": "```rust\npub fn foo() {} // missing #[inline]\nfn ok() {} // ok\n#[inline] pub fn bar() {} // ok\n#[inline(always)] pub fn baz() {} // ok\n\npub trait Bar {\n fn bar(); // ok\n fn def_bar() {} // missing #[inline]\n}\n\nstruct Baz;\nimpl Baz {\n fn private() {} // ok\n}\n\nimpl Bar for Baz {\n fn bar() {} // ok - Baz is not exported\n}\n\npub struct PubBaz;\nimpl PubBaz {\n fn private() {} // ok\n pub fn not_ptrivate() {} // missing #[inline]\n}\n\nimpl Bar for PubBaz {\n fn bar() {} // missing #[inline]\n fn def_bar() {} // missing #[inline]\n}\n```" + } + }, + { + "id": "missing_safety_doc", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for the doc comments of publicly visible\nunsafe functions and warns if there is no `# Safety` section.", + "Why is this bad": "Unsafe functions should document their safety\npreconditions, so that users can be sure they are using them safely.", + "Known problems": "None.", + "Examples": "```rust\n/// This function should really be documented\npub unsafe fn start_apocalypse(u: &mut Universe) {\n unimplemented!();\n}\n```\n\nAt least write a line about safety:\n\n```rust\n/// # Safety\n///\n/// This function should not be called before the horsemen are ready.\npub unsafe fn start_apocalypse(u: &mut Universe) {\n unimplemented!();\n}\n```" + } + }, + { + "id": "mistyped_literal_suffixes", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Warns for mistyped suffix in literals", + "Why is this bad": "This is most probably a typo", + "Known problems": "- Recommends a signed suffix, even though the number might be too big and an unsigned\n suffix is required\n- Does not match on `_127` since that is a valid grouping for decimal and octal numbers", + "Example": "```rust\n// Probably mistyped\n2_32;\n\n// Good\n2_i32;\n```" + } + }, + { + "id": "mixed_case_hex_literals", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Warns on hexadecimal literals with mixed-case letter\ndigits.", + "Why is this bad": "It looks confusing.", + "Known problems": "None.", + "Example": "```rust\n// Bad\nlet y = 0x1a9BAcD;\n\n// Good\nlet y = 0x1A9BACD;\n```" + } + }, + { + "id": "module_inception", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for modules that have the same name as their\nparent module", + "Why is this bad": "A typical beginner mistake is to have `mod foo;` and\nagain `mod foo { ..\n}` in `foo.rs`.\nThe expectation is that items inside the inner `mod foo { .. }` are then\navailable\nthrough `foo::x`, but they are only available through\n`foo::foo::x`.\nIf this is done on purpose, it would be better to choose a more\nrepresentative module name.", + "Known problems": "None.", + "Example": "```ignore\n// lib.rs\nmod foo;\n// foo.rs\nmod foo {\n ...\n}\n```" + } + }, + { + "id": "module_name_repetitions", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Detects type names that are prefixed or suffixed by the\ncontaining module's name.", + "Why is this bad": "It requires the user to type the module name twice.", + "Known problems": "None.", + "Example": "```rust\nmod cake {\n struct BlackForestCake;\n}\n```\nCould be written as:\n```rust\nmod cake {\n struct BlackForest;\n}\n```" + } + }, + { + "id": "modulo_arithmetic", + "group": "restriction", + "level": "Allow", + "docs": { + "What it does": "Checks for modulo arithemtic.", + "Why is this bad": "The results of modulo (%) operation might differ\ndepending on the language, when negative numbers are involved.\nIf you interop with different languages it might be beneficial\nto double check all places that use modulo arithmetic.\n\nFor example, in Rust `17 % -3 = 2`, but in Python `17 % -3 = -1`.", + "Known problems": "None.", + "Example": "```rust\nlet x = -17 % 3;\n```" + } + }, + { + "id": "modulo_one", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for getting the remainder of a division by one.", + "Why is this bad": "The result can only ever be zero. No one will write\nsuch code deliberately, unless trying to win an Underhanded Rust\nContest. Even for that contest, it's probably a bad idea. Use something more\nunderhanded.", + "Known problems": "None.", + "Example": "```rust\nlet a = x % 1;\n```" + } + }, + { + "id": "multiple_crate_versions", + "group": "cargo", + "level": "Allow", + "docs": { + "What it does": "Checks to see if multiple versions of a crate are being\nused.", + "Why is this bad": "This bloats the size of targets, and can lead to\nconfusing error messages when structs or traits are used interchangeably\nbetween different versions of a crate.", + "Known problems": "Because this can be caused purely by the dependencies\nthemselves, it's not always possible to fix this issue.", + "Example": "```toml\n# This will pull in both winapi v0.3.x and v0.2.x, triggering a warning.\n[dependencies]\nctrlc = \"=3.1.0\"\nansi_term = \"=0.11.0\"\n```" + } + }, + { + "id": "multiple_inherent_impl", + "group": "restriction", + "level": "Allow", + "docs": { + "What it does": "Checks for multiple inherent implementations of a struct", + "Why is this bad": "Splitting the implementation of a type makes the code harder to navigate.", + "Known problems": "None.", + "Example": "```rust\nstruct X;\nimpl X {\n fn one() {}\n}\nimpl X {\n fn other() {}\n}\n```\n\nCould be written:\n\n```rust\nstruct X;\nimpl X {\n fn one() {}\n fn other() {}\n}\n```" + } + }, + { + "id": "must_use_candidate", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for public functions that have no\n[`#[must_use]`] attribute, but return something not already marked\nmust-use, have no mutable arg and mutate no statics.\n\n[`#[must_use]`]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute", + "Why is this bad": "Not bad at all, this lint just shows places where\nyou could add the attribute.", + "Known problems": "The lint only checks the arguments for mutable\ntypes without looking if they are actually changed. On the other hand,\nit also ignores a broad range of potentially interesting side effects,\nbecause we cannot decide whether the programmer intends the function to\nbe called for the side effect or the result. Expect many false\npositives. At least we don't lint if the result type is unit or already\n`#[must_use]`.", + "Examples": "```rust\n// this could be annotated with `#[must_use]`.\nfn id(t: T) -> T { t }\n```" + } + }, + { + "id": "must_use_unit", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for a [`#[must_use]`] attribute on\nunit-returning functions and methods.\n\n[`#[must_use]`]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute", + "Why is this bad": "Unit values are useless. The attribute is likely\na remnant of a refactoring that removed the return type.", + "Known problems": "None.", + "Examples": "```rust\n#[must_use]\nfn useless() { }\n```" + } + }, + { + "id": "mut_from_ref", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "This lint checks for functions that take immutable\nreferences and return mutable ones.", + "Why is this bad": "This is trivially unsound, as one can create two\nmutable references from the same (immutable!) source.\nThis [error](https://github.com/rust-lang/rust/issues/39465)\nactually lead to an interim Rust release 1.15.1.", + "Known problems": "To be on the conservative side, if there's at least one\nmutable reference with the output lifetime, this lint will not trigger.\nIn practice, this case is unlikely anyway.", + "Example": "```ignore\nfn foo(&Foo) -> &mut Bar { .. }\n```" + } + }, + { + "id": "mut_mut", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for instances of `mut mut` references.", + "Why is this bad": "Multiple `mut`s don't add anything meaningful to the\nsource. This is either a copy'n'paste error, or it shows a fundamental\nmisunderstanding of references.", + "Known problems": "None.", + "Example": "```rust\nlet x = &mut &mut y;\n```" + } + }, + { + "id": "mut_range_bound", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for loops which have a range bound that is a mutable variable", + "Why is this bad": "One might think that modifying the mutable variable changes the loop bounds", + "Known problems": "None", + "Example": "```rust\nlet mut foo = 42;\nfor i in 0..foo {\n foo -= 1;\n println!(\"{}\", i); // prints numbers from 0 to 42, not 0 to 21\n}\n```" + } + }, + { + "id": "mutable_key_type", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for sets/maps with mutable key types.", + "Why is this bad": "All of `HashMap`, `HashSet`, `BTreeMap` and\n`BtreeSet` rely on either the hash or the order of keys be unchanging,\nso having types with interior mutability is a bad idea.", + "Known problems": "We don't currently account for `Rc` or `Arc`, so\nthis may yield false positives.", + "Example": "```rust\nuse std::cmp::{PartialEq, Eq};\nuse std::collections::HashSet;\nuse std::hash::{Hash, Hasher};\nuse std::sync::atomic::AtomicUsize;\n\nstruct Bad(AtomicUsize);\nimpl PartialEq for Bad {\n fn eq(&self, rhs: &Self) -> bool {\n ..\n; unimplemented!();\n }\n}\n\nimpl Eq for Bad {}\n\nimpl Hash for Bad {\n fn hash(&self, h: &mut H) {\n ..\n; unimplemented!();\n }\n}\n\nfn main() {\n let _: HashSet = HashSet::new();\n}\n```" + } + }, + { + "id": "mutex_atomic", + "group": "perf", + "level": "Warn", + "docs": { + "What it does": "Checks for usages of `Mutex` where an atomic will do.", + "Why is this bad": "Using a mutex just to make access to a plain bool or\nreference sequential is shooting flies with cannons.\n`std::sync::atomic::AtomicBool` and `std::sync::atomic::AtomicPtr` are leaner and\nfaster.", + "Known problems": "This lint cannot detect if the mutex is actually used\nfor waiting before a critical section.", + "Example": "```rust\n\n// Bad\nlet x = Mutex::new(&y);\n\n// Good\nlet x = AtomicBool::new(y);\n```" + } + }, + { + "id": "mutex_integer", + "group": "nursery", + "level": "Allow", + "docs": { + "What it does": "Checks for usages of `Mutex` where `X` is an integral\ntype.", + "Why is this bad": "Using a mutex just to make access to a plain integer\nsequential is\nshooting flies with cannons. `std::sync::atomic::AtomicUsize` is leaner and faster.", + "Known problems": "This lint cannot detect if the mutex is actually used\nfor waiting before a critical section.", + "Example": "```rust\nlet x = Mutex::new(0usize);\n\n// Good\nlet x = AtomicUsize::new(0usize);\n```" + } + }, + { + "id": "naive_bytecount", + "group": "perf", + "level": "Warn", + "docs": { + "What it does": "Checks for naive byte counts", + "Why is this bad": "The [`bytecount`](https://crates.io/crates/bytecount)\ncrate has methods to count your bytes faster, especially for large slices.", + "Known problems": "If you have predominantly small slices, the\n`bytecount::count(..)` method may actually be slower. However, if you can\nensure that less than 2\u00b3\u00b2-1 matches arise, the `naive_count_32(..)` can be\nfaster in those cases.", + "Example": "```rust\n&vec.iter().filter(|x| **x == 0u8).count(); // use bytecount::count instead\n```" + } + }, + { + "id": "needless_bool", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for expressions of the form `if c { true } else {\nfalse }` (or vice versa) and suggests using the condition directly.", + "Why is this bad": "Redundant code.", + "Known problems": "Maybe false positives: Sometimes, the two branches are\npainstakingly documented (which we, of course, do not detect), so they *may*\nhave some value. Even then, the documentation can be rewritten to match the\nshorter code.", + "Example": "```rust,ignore\nif x {\n false\n} else {\n true\n}\n```\nCould be written as\n```rust,ignore\n!x\n```" + } + }, + { + "id": "needless_borrow", + "group": "nursery", + "level": "Allow", + "docs": { + "What it does": "Checks for address of operations (`&`) that are going to\nbe dereferenced immediately by the compiler.", + "Why is this bad": "Suggests that the receiver of the expression borrows\nthe expression.", + "Known problems": "None.", + "Example": "```rust\n// Bad\nlet x: &i32 = &&&&&&5;\n\n// Good\nlet x: &i32 = &5;\n```" + } + }, + { + "id": "needless_borrowed_reference", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for useless borrowed references.", + "Why is this bad": "It is mostly useless and make the code look more\ncomplex than it\nactually is.", + "Known problems": "It seems that the `&ref` pattern is sometimes useful.\nFor instance in the following snippet:\n```rust,ignore\nenum Animal {\n Cat(u64),\n Dog(u64),\n}\n\nfn foo(a: &Animal, b: &Animal) {\n match (a, b) {\n (&Animal::Cat(v), k) | (k, &Animal::Cat(v)) => (), // lifetime mismatch error\n (&Animal::Dog(ref c), &Animal::Dog(_)) => ()\n }\n}\n```\nThere is a lifetime mismatch error for `k` (indeed a and b have distinct\nlifetime).\nThis can be fixed by using the `&ref` pattern.\nHowever, the code can also be fixed by much cleaner ways", + "Example": "```rust\nlet mut v = Vec::::new();\nlet _ = v.iter_mut().filter(|&ref a| a.is_empty());\n```\nThis closure takes a reference on something that has been matched as a\nreference and\nde-referenced.\nAs such, it could just be |a| a.is_empty()" + } + }, + { + "id": "needless_collect", + "group": "perf", + "level": "Warn", + "docs": { + "What it does": "Checks for functions collecting an iterator when collect\nis not needed.", + "Why is this bad": "`collect` causes the allocation of a new data structure,\nwhen this allocation may not be needed.", + "Known problems": "None", + "Example": "```rust\nlet len = iterator.clone().collect::>().len();\n// should be\nlet len = iterator.count();\n```" + } + }, + { + "id": "needless_continue", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "The lint checks for `if`-statements appearing in loops\nthat contain a `continue` statement in either their main blocks or their\n`else`-blocks, when omitting the `else`-block possibly with some\nrearrangement of code can make the code easier to understand.", + "Why is this bad": "Having explicit `else` blocks for `if` statements\ncontaining `continue` in their THEN branch adds unnecessary branching and\nnesting to the code. Having an else block containing just `continue` can\nalso be better written by grouping the statements following the whole `if`\nstatement within the THEN block and omitting the else block completely.", + "Known problems": "None", + "Example": "```rust\nwhile condition() {\n update_condition();\n if x {\n // ...\n } else {\n continue;\n }\n println!(\"Hello, world\");\n}\n```\n\nCould be rewritten as\n\n```rust\nwhile condition() {\n update_condition();\n if x {\n // ...\n println!(\"Hello, world\");\n }\n}\n```\n\nAs another example, the following code\n\n```rust\nloop {\n if waiting() {\n continue;\n } else {\n // Do something useful\n }\n # break;\n}\n```\nCould be rewritten as\n\n```rust\nloop {\n if waiting() {\n continue;\n }\n // Do something useful\n # break;\n}\n```" + } + }, + { + "id": "needless_doctest_main", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for `fn main() { .. }` in doctests", + "Why is this bad": "The test can be shorter (and likely more readable)\nif the `fn main()` is left implicit.", + "Known problems": "None.", + "Examples": "``````rust\n/// An example of a doctest with a `main()` function\n///\n/// # Examples\n///\n/// ```\n/// fn main() {\n/// // this needs not be in an `fn`\n/// }\n/// ```\nfn needless_main() {\n unimplemented!();\n}\n``````" + } + }, + { + "id": "needless_lifetimes", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for lifetime annotations which can be removed by\nrelying on lifetime elision.", + "Why is this bad": "The additional lifetimes make the code look more\ncomplicated, while there is nothing out of the ordinary going on. Removing\nthem leads to more readable code.", + "Known problems": "Potential false negatives: we bail out if the function\nhas a `where` clause where lifetimes are mentioned.", + "Example": "```rust\n// Bad: unnecessary lifetime annotations\nfn in_and_out<'a>(x: &'a u8, y: u8) -> &'a u8 {\n x\n}\n\n// Good\nfn elided(x: &u8, y: u8) -> &u8 {\n x\n}\n```" + } + }, + { + "id": "needless_pass_by_value", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for functions taking arguments by value, but not\nconsuming them in its\nbody.", + "Why is this bad": "Taking arguments by reference is more flexible and can\nsometimes avoid\nunnecessary allocations.", + "Known problems": "* This lint suggests taking an argument by reference,\nhowever sometimes it is better to let users decide the argument type\n(by using `Borrow` trait, for example), depending on how the function is used.", + "Example": "```rust\nfn foo(v: Vec) {\n assert_eq!(v.len(), 42);\n}\n```\nshould be\n```rust\nfn foo(v: &[i32]) {\n assert_eq!(v.len(), 42);\n}\n```" + } + }, + { + "id": "needless_range_loop", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for looping over the range of `0..len` of some\ncollection just to get the values by index.", + "Why is this bad": "Just iterating the collection itself makes the intent\nmore clear and is probably faster.", + "Known problems": "None.", + "Example": "```rust\nlet vec = vec!['a', 'b', 'c'];\nfor i in 0..vec.len() {\n println!(\"{}\", vec[i]);\n}\n```\nCould be written as:\n```rust\nlet vec = vec!['a', 'b', 'c'];\nfor i in vec {\n println!(\"{}\", i);\n}\n```" + } + }, + { + "id": "needless_return", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for return statements at the end of a block.", + "Why is this bad": "Removing the `return` and semicolon will make the code\nmore rusty.", + "Known problems": "If the computation returning the value borrows a local\nvariable, removing the `return` may run afoul of the borrow checker.", + "Example": "```rust\nfn foo(x: usize) -> usize {\n return x;\n}\n```\nsimplify to\n```rust\nfn foo(x: usize) -> usize {\n x\n}\n```" + } + }, + { + "id": "needless_update", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for needlessly including a base struct on update\nwhen all fields are changed anyway.", + "Why is this bad": "This will cost resources (because the base has to be\nsomewhere), and make the code less readable.", + "Known problems": "None.", + "Example": "```rust\n\n// Bad\nPoint {\n x: 1,\n y: 1,\n z: 1,\n ..zero_point\n};\n\n// Ok\nPoint {\n x: 1,\n y: 1,\n ..zero_point\n};\n```" + } + }, + { + "id": "neg_cmp_op_on_partial_ord", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for the usage of negated comparison operators on types which only implement\n`PartialOrd` (e.g., `f64`).", + "Why is this bad": "These operators make it easy to forget that the underlying types actually allow not only three\npotential Orderings (Less, Equal, Greater) but also a fourth one (Uncomparable). This is\nespecially easy to miss if the operator based comparison result is negated.", + "Known problems": "None.", + "Example": "```rust\nuse std::cmp::Ordering;\n\n// Bad\nlet a = 1.0;\nlet b = f64::NAN;\n\nlet _not_less_or_equal = !(a <= b);\n\n// Good\nlet a = 1.0;\nlet b = f64::NAN;\n\nlet _not_less_or_equal = match a.partial_cmp(&b) {\n None | Some(Ordering::Greater) => true,\n _ => false,\n};\n```" + } + }, + { + "id": "neg_multiply", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for multiplication by -1 as a form of negation.", + "Why is this bad": "It's more readable to just negate.", + "Known problems": "This only catches integers (for now).", + "Example": "```ignore\nx * -1\n```" + } + }, + { + "id": "never_loop", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for loops that will always `break`, `return` or\n`continue` an outer loop.", + "Why is this bad": "This loop never loops, all it does is obfuscating the\ncode.", + "Known problems": "None", + "Example": "```rust\nloop {\n ..;\n break;\n}\n```" + } + }, + { + "id": "new_ret_no_self", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for `new` not returning a type that contains `Self`.", + "Why is this bad": "As a convention, `new` methods are used to make a new\ninstance of a type.", + "Known problems": "None.", + "Example": "```rust\nimpl Foo {\n fn new() -> NotAFoo {\n }\n}\n```\n\n```rust\nimpl Foo {\n // Good. Return type contains `Self`\n fn new() -> Result {\n # Ok(Foo)\n }\n}\n```\n\n```rust\nstruct Bar(Foo);\nimpl Foo {\n // Bad. The type name must contain `Self`.\n fn new() -> Bar {\n # Bar(Foo)\n }\n}\n```" + } + }, + { + "id": "new_without_default", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for types with a `fn new() -> Self` method and no\nimplementation of\n[`Default`](https://doc.rust-lang.org/std/default/trait.Default.html).", + "Why is this bad": "The user might expect to be able to use\n[`Default`](https://doc.rust-lang.org/std/default/trait.Default.html) as the\ntype can be constructed without arguments.", + "Known problems": "Hopefully none.", + "Example": "```ignore\nstruct Foo(Bar);\n\nimpl Foo {\n fn new() -> Self {\n Foo(Bar::new())\n }\n}\n```\n\nTo fix the lint, add a `Default` implementation that delegates to `new`:\n\n```ignore\nstruct Foo(Bar);\n\nimpl Default for Foo {\n fn default() -> Self {\n Foo::new()\n }\n}\n```" + } + }, + { + "id": "no_effect", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for statements which have no effect.", + "Why is this bad": "Similar to dead code, these statements are actually\nexecuted. However, as they have no effect, all they do is make the code less\nreadable.", + "Known problems": "None.", + "Example": "```rust\n0;\n```" + } + }, + { + "id": "non_ascii_literal", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for non-ASCII characters in string literals.", + "Why is this bad": "Yeah, we know, the 90's called and wanted their charset\nback. Even so, there still are editors and other programs out there that\ndon't work well with Unicode. So if the code is meant to be used\ninternationally, on multiple operating systems, or has other portability\nrequirements, activating this lint could be useful.", + "Known problems": "None.", + "Example": "```rust\nlet x = String::from(\"\u20ac\");\n```\nCould be written as:\n```rust\nlet x = String::from(\"\\u{20ac}\");\n```" + } + }, + { + "id": "nonminimal_bool", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for boolean expressions that can be written more\nconcisely.", + "Why is this bad": "Readability of boolean expressions suffers from\nunnecessary duplication.", + "Known problems": "Ignores short circuiting behavior of `||` and\n`&&`. Ignores `|`, `&` and `^`.", + "Example": "```ignore\nif a && true // should be: if a\nif !(a == b) // should be: if a != b\n```" + } + }, + { + "id": "nonsensical_open_options", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for duplicate open options as well as combinations\nthat make no sense.", + "Why is this bad": "In the best case, the code will be harder to read than\nnecessary. I don't know the worst case.", + "Known problems": "None.", + "Example": "```rust\nuse std::fs::OpenOptions;\n\nOpenOptions::new().read(true).truncate(true);\n```" + } + }, + { + "id": "not_unsafe_ptr_arg_deref", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for public functions that dereference raw pointer\narguments but are not marked unsafe.", + "Why is this bad": "The function should probably be marked `unsafe`, since\nfor an arbitrary raw pointer, there is no way of telling for sure if it is\nvalid.", + "Known problems": "* It does not check functions recursively so if the pointer is passed to a\nprivate non-`unsafe` function which does the dereferencing, the lint won't\ntrigger.\n* It only checks for arguments whose type are raw pointers, not raw pointers\ngot from an argument in some other way (`fn foo(bar: &[*const u8])` or\n`some_argument.get_raw_ptr()`).", + "Example": "```rust,ignore\n// Bad\npub fn foo(x: *const u8) {\n println!(\"{}\", unsafe { *x });\n}\n\n// Good\npub unsafe fn foo(x: *const u8) {\n println!(\"{}\", unsafe { *x });\n}\n```" + } + }, + { + "id": "ok_expect", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for usage of `ok().expect(..)`.", + "Why is this bad": "Because you usually call `expect()` on the `Result`\ndirectly to get a better error message.", + "Known problems": "The error type needs to implement `Debug`", + "Example": "```rust\n\n// Bad\nx.ok().expect(\"why did I do this again?\");\n\n// Good\nx.expect(\"why did I do this again?\");\n```" + } + }, + { + "id": "op_ref", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for arguments to `==` which have their address\ntaken to satisfy a bound\nand suggests to dereference the other argument instead", + "Why is this bad": "It is more idiomatic to dereference the other argument.", + "Known problems": "None", + "Example": "```ignore\n// Bad\n&x == y\n\n// Good\nx == *y\n```" + } + }, + { + "id": "option_as_ref_deref", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for usage of `_.as_ref().map(Deref::deref)` or it's aliases (such as String::as_str).", + "Why is this bad": "Readability, this can be written more concisely as a\nsingle method call.", + "Known problems": "None.", + "Example": "```rust\nopt.as_ref().map(String::as_str)\n```\nCan be written as\n```rust\nopt.as_deref()\n```" + } + }, + { + "id": "option_env_unwrap", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for usage of `option_env!(...).unwrap()` and\nsuggests usage of the `env!` macro.", + "Why is this bad": "Unwrapping the result of `option_env!` will panic\nat run-time if the environment variable doesn't exist, whereas `env!`\ncatches it at compile-time.", + "Known problems": "None.", + "Example": "```rust,no_run\nlet _ = option_env!(\"HOME\").unwrap();\n```\n\nIs better expressed as:\n\n```rust,no_run\nlet _ = env!(\"HOME\");\n```" + } + }, + { + "id": "option_map_or_none", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for usage of `_.map_or(None, _)`.", + "Why is this bad": "Readability, this can be written more concisely as\n`_.and_then(_)`.", + "Known problems": "The order of the arguments is not in execution order.", + "Example": "```rust\n\n// Bad\nopt.map_or(None, |a| Some(a + 1));\n\n// Good\nopt.and_then(|a| Some(a + 1));\n```" + } + }, + { + "id": "option_map_unit_fn", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for usage of `option.map(f)` where f is a function\nor closure that returns the unit type.", + "Why is this bad": "Readability, this can be written more clearly with\nan if let statement", + "Known problems": "None.", + "Example": "```rust\nlet x: Option = do_stuff();\nx.map(log_err_msg);\nx.map(|msg| log_err_msg(format_msg(msg)));\n```\n\nThe correct use would be:\n\n```rust\nlet x: Option = do_stuff();\nif let Some(msg) = x {\n log_err_msg(msg);\n}\n\nif let Some(msg) = x {\n log_err_msg(format_msg(msg));\n}\n```" + } + }, + { + "id": "option_option", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for use of `Option>` in function signatures and type\ndefinitions", + "Why is this bad": "`Option<_>` represents an optional value. `Option>`\nrepresents an optional optional value which is logically the same thing as an optional\nvalue but has an unneeded extra level of wrapping.\n\nIf you have a case where `Some(Some(_))`, `Some(None)` and `None` are distinct cases,\nconsider a custom `enum` instead, with clear names for each case.", + "Known problems": "None.", + "Example": "```rust\nfn get_data() -> Option> {\n None\n}\n```\n\nBetter:\n\n```rust\npub enum Contents {\n Data(Vec), // Was Some(Some(Vec))\n NotYetFetched, // Was Some(None)\n None, // Was None\n}\n\nfn get_data() -> Contents {\n Contents::None\n}\n```" + } + }, + { + "id": "or_fun_call", + "group": "perf", + "level": "Warn", + "docs": { + "What it does": "Checks for calls to `.or(foo(..))`, `.unwrap_or(foo(..))`,\netc., and suggests to use `or_else`, `unwrap_or_else`, etc., or\n`unwrap_or_default` instead.", + "Why is this bad": "The function will always be called and potentially\nallocate an object acting as the default.", + "Known problems": "If the function has side-effects, not calling it will\nchange the semantic of the program, but you shouldn't rely on that anyway.", + "Example": "```rust\nfoo.unwrap_or(String::new());\n```\nthis can instead be written:\n```rust\nfoo.unwrap_or_else(String::new);\n```\nor\n```rust\nfoo.unwrap_or_default();\n```" + } + }, + { + "id": "out_of_bounds_indexing", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for out of bounds array indexing with a constant\nindex.", + "Why is this bad": "This will always panic at runtime.", + "Known problems": "Hopefully none.", + "Example": "```no_run\n# #![allow(const_err)]\nlet x = [1, 2, 3, 4];\n\n// Bad\nx[9];\n&x[2..9];\n\n// Good\nx[0];\nx[3];\n```" + } + }, + { + "id": "overflow_check_conditional", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Detects classic underflow/overflow checks.", + "Why is this bad": "Most classic C underflow/overflow checks will fail in\nRust. Users can use functions like `overflowing_*` and `wrapping_*` instead.", + "Known problems": "None.", + "Example": "```rust\na + b < a;\n```" + } + }, + { + "id": "panic", + "group": "restriction", + "level": "Allow", + "docs": { + "What it does": "Checks for usage of `panic!`.", + "Why is this bad": "`panic!` will stop the execution of the executable", + "Known problems": "None.", + "Example": "```no_run\npanic!(\"even with a good reason\");\n```" + } + }, + { + "id": "panic_params", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for missing parameters in `panic!`.", + "Why is this bad": "Contrary to the `format!` family of macros, there are\ntwo forms of `panic!`: if there are no parameters given, the first argument\nis not a format string and used literally. So while `format!(\"{}\")` will\nfail to compile, `panic!(\"{}\")` will not.", + "Known problems": "None.", + "Example": "```no_run\npanic!(\"This `panic!` is probably missing a parameter there: {}\");\n```" + } + }, + { + "id": "panicking_unwrap", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for calls of `unwrap[_err]()` that will always fail.", + "Why is this bad": "If panicking is desired, an explicit `panic!()` should be used.", + "Known problems": "This lint only checks `if` conditions not assignments.\nSo something like `let x: Option<()> = None; x.unwrap();` will not be recognized.", + "Example": "```rust\nif option.is_none() {\n do_something_with(option.unwrap())\n}\n```\n\nThis code will always panic. The if condition should probably be inverted." + } + }, + { + "id": "partialeq_ne_impl", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for manual re-implementations of `PartialEq::ne`.", + "Why is this bad": "`PartialEq::ne` is required to always return the\nnegated result of `PartialEq::eq`, which is exactly what the default\nimplementation does. Therefore, there should never be any need to\nre-implement it.", + "Known problems": "None.", + "Example": "```rust\nstruct Foo;\n\nimpl PartialEq for Foo {\n fn eq(&self, other: &Foo) -> bool { true }\n fn ne(&self, other: &Foo) -> bool { !(self == other) }\n}\n```" + } + }, + { + "id": "path_buf_push_overwrite", + "group": "nursery", + "level": "Allow", + "docs": { + "What it does": "* Checks for [push](https://doc.rust-lang.org/std/path/struct.PathBuf.html#method.push)\ncalls on `PathBuf` that can cause overwrites.", + "Why is this bad": "Calling `push` with a root path at the start can overwrite the\nprevious defined path.", + "Known problems": "None.", + "Example": "```rust\nuse std::path::PathBuf;\n\nlet mut x = PathBuf::from(\"/foo\");\nx.push(\"/bar\");\nassert_eq!(x, PathBuf::from(\"/bar\"));\n```\nCould be written:\n\n```rust\nuse std::path::PathBuf;\n\nlet mut x = PathBuf::from(\"/foo\");\nx.push(\"bar\");\nassert_eq!(x, PathBuf::from(\"/foo/bar\"));\n```" + } + }, + { + "id": "possible_missing_comma", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for possible missing comma in an array. It lints if\nan array element is a binary operator expression and it lies on two lines.", + "Why is this bad": "This could lead to unexpected results.", + "Known problems": "None.", + "Example": "```rust,ignore\nlet a = &[\n -1, -2, -3 // <= no comma here\n -4, -5, -6\n];\n```" + } + }, + { + "id": "precedence", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for operations where precedence may be unclear\nand suggests to add parentheses. Currently it catches the following:\n* mixed usage of arithmetic and bit shifting/combining operators without\nparentheses\n* a \"negative\" numeric literal (which is really a unary `-` followed by a\nnumeric literal)\n followed by a method call", + "Why is this bad": "Not everyone knows the precedence of those operators by\nheart, so expressions like these may trip others trying to reason about the\ncode.", + "Known problems": "None.", + "Example": "* `1 << 2 + 3` equals 32, while `(1 << 2) + 3` equals 7\n* `-1i32.abs()` equals -1, while `(-1i32).abs()` equals 1" + } + }, + { + "id": "print_literal", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "This lint warns about the use of literals as `print!`/`println!` args.", + "Why is this bad": "Using literals as `println!` args is inefficient\n(c.f., https://github.com/matthiaskrgr/rust-str-bench) and unnecessary\n(i.e., just put the literal in the format string)", + "Known problems": "Will also warn with macro calls as arguments that expand to literals\n-- e.g., `println!(\"{}\", env!(\"FOO\"))`.", + "Example": "```rust\nprintln!(\"{}\", \"foo\");\n```\nuse the literal without formatting:\n```rust\nprintln!(\"foo\");\n```" + } + }, + { + "id": "print_stdout", + "group": "restriction", + "level": "Allow", + "docs": { + "What it does": "Checks for printing on *stdout*. The purpose of this lint\nis to catch debugging remnants.", + "Why is this bad": "People often print on *stdout* while debugging an\napplication and might forget to remove those prints afterward.", + "Known problems": "Only catches `print!` and `println!` calls.", + "Example": "```rust\nprintln!(\"Hello world!\");\n```" + } + }, + { + "id": "print_with_newline", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "This lint warns when you use `print!()` with a format\nstring that ends in a newline.", + "Why is this bad": "You should use `println!()` instead, which appends the\nnewline.", + "Known problems": "None.", + "Example": "```rust\nprint!(\"Hello {}!\\n\", name);\n```\nuse println!() instead\n```rust\nprintln!(\"Hello {}!\", name);\n```" + } + }, + { + "id": "println_empty_string", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "This lint warns when you use `println!(\"\")` to\nprint a newline.", + "Why is this bad": "You should use `println!()`, which is simpler.", + "Known problems": "None.", + "Example": "```rust\n// Bad\nprintln!(\"\");\n\n// Good\nprintln!();\n```" + } + }, + { + "id": "ptr_arg", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "This lint checks for function arguments of type `&String`\nor `&Vec` unless the references are mutable. It will also suggest you\nreplace `.clone()` calls with the appropriate `.to_owned()`/`to_string()`\ncalls.", + "Why is this bad": "Requiring the argument to be of the specific size\nmakes the function less useful for no benefit; slices in the form of `&[T]`\nor `&str` usually suffice and can be obtained from other types, too.", + "Known problems": "The lint does not follow data. So if you have an\nargument `x` and write `let y = x; y.clone()` the lint will not suggest\nchanging that `.clone()` to `.to_owned()`.\n\nOther functions called from this function taking a `&String` or `&Vec`\nargument may also fail to compile if you change the argument. Applying\nthis lint on them will fix the problem, but they may be in other crates.\n\nAlso there may be `fn(&Vec)`-typed references pointing to your function.\nIf you have them, you will get a compiler error after applying this lint's\nsuggestions. You then have the choice to undo your changes or change the\ntype of the reference.\n\nNote that if the function is part of your public interface, there may be\nother crates referencing it you may not be aware. Carefully deprecate the\nfunction before applying the lint suggestions in this case.", + "Example": "```ignore\n// Bad\nfn foo(&Vec) { .. }\n\n// Good\nfn foo(&[u32]) { .. }\n```" + } + }, + { + "id": "ptr_offset_with_cast", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for usage of the `offset` pointer method with a `usize` casted to an\n`isize`.", + "Why is this bad": "If we\u2019re always increasing the pointer address, we can avoid the numeric\ncast by using the `add` method instead.", + "Known problems": "None", + "Example": "```rust\nlet vec = vec![b'a', b'b', b'c'];\nlet ptr = vec.as_ptr();\nlet offset = 1_usize;\n\nunsafe {\n ptr.offset(offset as isize);\n}\n```\n\nCould be written:\n\n```rust\nlet vec = vec![b'a', b'b', b'c'];\nlet ptr = vec.as_ptr();\nlet offset = 1_usize;\n\nunsafe {\n ptr.add(offset);\n}\n```" + } + }, + { + "id": "pub_enum_variant_names", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Detects public enumeration variants that are\nprefixed or suffixed by the same characters.", + "Why is this bad": "Public enumeration variant names should specify their variant,\nnot repeat the enumeration name.", + "Known problems": "None.", + "Example": "```rust\npub enum Cake {\n BlackForestCake,\n HummingbirdCake,\n BattenbergCake,\n}\n```\nCould be written as:\n```rust\npub enum Cake {\n BlackForest,\n Hummingbird,\n Battenberg,\n}\n```" + } + }, + { + "id": "question_mark", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for expressions that could be replaced by the question mark operator.", + "Why is this bad": "Question mark usage is more idiomatic.", + "Known problems": "None", + "Example": "```ignore\nif option.is_none() {\n return None;\n}\n```\n\nCould be written:\n\n```ignore\noption?;\n```" + } + }, + { + "id": "range_minus_one", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for inclusive ranges where 1 is subtracted from\nthe upper bound, e.g., `x..=(y-1)`.", + "Why is this bad": "The code is more readable with an exclusive range\nlike `x..y`.", + "Known problems": "None.", + "Example": "```rust,ignore\nfor x..=(y-1) { .. }\n```\nCould be written as\n```rust,ignore\nfor x..y { .. }\n```" + } + }, + { + "id": "range_plus_one", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for exclusive ranges where 1 is added to the\nupper bound, e.g., `x..(y+1)`.", + "Why is this bad": "The code is more readable with an inclusive range\nlike `x..=y`.", + "Known problems": "Will add unnecessary pair of parentheses when the\nexpression is not wrapped in a pair but starts with a opening parenthesis\nand ends with a closing one.\nI.e., `let _ = (f()+1)..(f()+1)` results in `let _ = ((f()+1)..=f())`.\n\nAlso in many cases, inclusive ranges are still slower to run than\nexclusive ranges, because they essentially add an extra branch that\nLLVM may fail to hoist out of the loop.", + "Example": "```rust,ignore\nfor x..(y+1) { .. }\n```\nCould be written as\n```rust,ignore\nfor x..=y { .. }\n```" + } + }, + { + "id": "range_step_by_zero", + "group": "deprecated", + "level": "Deprecated", + "docs": { + "What it does": "Nothing. This lint has been deprecated.", + "Deprecation reason": "`Range::step_by(0)` used to be linted since it's\nan infinite iterator, which is better expressed by `iter::repeat`,\nbut the method has been removed for `Iterator::step_by` which panics\nif given a zero" + } + }, + { + "id": "range_zip_with_len", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for zipping a collection with the range of\n`0.._.len()`.", + "Why is this bad": "The code is better expressed with `.enumerate()`.", + "Known problems": "None.", + "Example": "```rust\nx.iter().zip(0..x.len());\n```\nCould be written as\n```rust\nx.iter().enumerate();\n```" + } + }, + { + "id": "redundant_allocation", + "group": "perf", + "level": "Warn", + "docs": { + "What it does": "Checks for use of redundant allocations anywhere in the code.", + "Why is this bad": "Expressions such as `Rc<&T>`, `Rc>`, `Rc>`, `Box<&T>`\nadd an unnecessary level of indirection.", + "Known problems": "None.", + "Example": "```rust\nfn foo(bar: Rc<&usize>) {}\n```\n\nBetter:\n\n```rust\nfn foo(bar: &usize) {}\n```" + } + }, + { + "id": "redundant_clone", + "group": "perf", + "level": "Warn", + "docs": { + "What it does": "Checks for a redundant `clone()` (and its relatives) which clones an owned\nvalue that is going to be dropped without further use.", + "Why is this bad": "It is not always possible for the compiler to eliminate useless\nallocations and deallocations generated by redundant `clone()`s.", + "Known problems": "False-negatives: analysis performed by this lint is conservative and limited.", + "Example": "```rust\n{\n let x = Foo::new();\n call(x.clone());\n call(x.clone()); // this can just pass `x`\n}\n\n[\"lorem\", \"ipsum\"].join(\" \").to_string();\n\nPath::new(\"/a/b\").join(\"c\").to_path_buf();\n```" + } + }, + { + "id": "redundant_closure", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for closures which just call another function where\nthe function can be called directly. `unsafe` functions or calls where types\nget adjusted are ignored.", + "Why is this bad": "Needlessly creating a closure adds code for no benefit\nand gives the optimizer more work.", + "Known problems": "If creating the closure inside the closure has a side-\neffect then moving the closure creation out will change when that side-\neffect runs.\nSee rust-lang/rust-clippy#1439 for more details.", + "Example": "```rust,ignore\n// Bad\nxs.map(|x| foo(x))\n\n// Good\nxs.map(foo)\n```\nwhere `foo(_)` is a plain function that takes the exact argument type of\n`x`." + } + }, + { + "id": "redundant_closure_call", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Detects closures called in the same expression where they\nare defined.", + "Why is this bad": "It is unnecessarily adding to the expression's\ncomplexity.", + "Known problems": "None.", + "Example": "```rust,ignore\n// Bad\nlet a = (|| 42)()\n\n// Good\nlet a = 42\n```" + } + }, + { + "id": "redundant_closure_for_method_calls", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for closures which only invoke a method on the closure\nargument and can be replaced by referencing the method directly.", + "Why is this bad": "It's unnecessary to create the closure.", + "Known problems": "rust-lang/rust-clippy#3071, rust-lang/rust-clippy#4002,\nrust-lang/rust-clippy#3942", + "Example": "```rust,ignore\nSome('a').map(|s| s.to_uppercase());\n```\nmay be rewritten as\n```rust,ignore\nSome('a').map(char::to_uppercase);\n```" + } + }, + { + "id": "redundant_field_names", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for fields in struct literals where shorthands\ncould be used.", + "Why is this bad": "If the field and variable names are the same,\nthe field name is redundant.", + "Known problems": "None.", + "Example": "```rust\nlet bar: u8 = 123;\n\nstruct Foo {\n bar: u8,\n}\n\nlet foo = Foo { bar: bar };\n```\nthe last line can be simplified to\n```ignore\nlet foo = Foo { bar };\n```" + } + }, + { + "id": "redundant_pattern", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for patterns in the form `name @ _`.", + "Why is this bad": "It's almost always more readable to just use direct\nbindings.", + "Known problems": "None.", + "Example": "```rust\n\n// Bad\nmatch v {\n Some(x) => (),\n y @ _ => (),\n}\n\n// Good\nmatch v {\n Some(x) => (),\n y => (),\n}\n```" + } + }, + { + "id": "redundant_pattern_matching", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Lint for redundant pattern matching over `Result` or\n`Option`", + "Why is this bad": "It's more concise and clear to just use the proper\nutility function", + "Known problems": "None.", + "Example": "```rust\nif let Ok(_) = Ok::(42) {}\nif let Err(_) = Err::(42) {}\nif let None = None::<()> {}\nif let Some(_) = Some(42) {}\nmatch Ok::(42) {\n Ok(_) => true,\n Err(_) => false,\n};\n```\n\nThe more idiomatic use would be:\n\n```rust\nif Ok::(42).is_ok() {}\nif Err::(42).is_err() {}\nif None::<()>.is_none() {}\nif Some(42).is_some() {}\nOk::(42).is_ok();\n```" + } + }, + { + "id": "redundant_pub_crate", + "group": "nursery", + "level": "Allow", + "docs": { + "What it does": "Checks for items declared `pub(crate)` that are not crate visible because they\nare inside a private module.", + "Why is this bad": "Writing `pub(crate)` is misleading when it's redundant due to the parent\nmodule's visibility.", + "Known problems": "None.", + "Example": "```rust\nmod internal {\n pub(crate) fn internal_fn() { }\n}\n```\nThis function is not visible outside the module and it can be declared with `pub` or\nprivate visibility\n```rust\nmod internal {\n pub fn internal_fn() { }\n}\n```" + } + }, + { + "id": "redundant_static_lifetimes", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for constants and statics with an explicit `'static` lifetime.", + "Why is this bad": "Adding `'static` to every reference can create very\ncomplicated types.", + "Known problems": "None.", + "Example": "```ignore\nconst FOO: &'static [(&'static str, &'static str, fn(&Bar) -> bool)] =\n&[...]\nstatic FOO: &'static [(&'static str, &'static str, fn(&Bar) -> bool)] =\n&[...]\n```\nThis code can be rewritten as\n```ignore\n const FOO: &[(&str, &str, fn(&Bar) -> bool)] = &[...]\n static FOO: &[(&str, &str, fn(&Bar) -> bool)] = &[...]\n```" + } + }, + { + "id": "ref_in_deref", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for references in expressions that use\nauto dereference.", + "Why is this bad": "The reference is a no-op and is automatically\ndereferenced by the compiler and makes the code less clear.", + "Example": "```rust\nstruct Point(u32, u32);\nlet point = Point(30, 20);\nlet x = (&point).0;\n```" + } + }, + { + "id": "regex_macro", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for usage of `regex!(_)` which (as of now) is\nusually slower than `Regex::new(_)` unless called in a loop (which is a bad\nidea anyway).", + "Why is this bad": "Performance, at least for now. The macro version is\nlikely to catch up long-term, but for now the dynamic version is faster.", + "Known problems": "None.", + "Example": "```ignore\nregex!(\"foo|bar\")\n```" + } + }, + { + "id": "replace_consts", + "group": "deprecated", + "level": "Deprecated", + "docs": { + "What it does": "Nothing. This lint has been deprecated.", + "Deprecation reason": "Associated-constants are now preferred." + } + }, + { + "id": "rest_pat_in_fully_bound_structs", + "group": "restriction", + "level": "Allow", + "docs": { + "What it does": "Checks for unnecessary '..' pattern binding on struct when all fields are explicitly matched.", + "Why is this bad": "Correctness and readability. It's like having a wildcard pattern after\nmatching all enum variants explicitly.", + "Known problems": "None.", + "Example": "```rust\nlet a = A { a: 5 };\n\n// Bad\nmatch a {\n A { a: 5, .. } => {},\n _ => {},\n}\n\n// Good\nmatch a {\n A { a: 5 } => {},\n _ => {},\n}\n```" + } + }, + { + "id": "result_map_or_into_option", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for usage of `_.map_or(None, Some)`.", + "Why is this bad": "Readability, this can be written more concisely as\n`_.ok()`.", + "Known problems": "None.", + "Example": "Bad:\n```rust\nassert_eq!(Some(1), r.map_or(None, Some));\n```\n\nGood:\n```rust\nassert_eq!(Some(1), r.ok());\n```" + } + }, + { + "id": "result_map_unit_fn", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for usage of `result.map(f)` where f is a function\nor closure that returns the unit type.", + "Why is this bad": "Readability, this can be written more clearly with\nan if let statement", + "Known problems": "None.", + "Example": "```rust\nlet x: Result = do_stuff();\nx.map(log_err_msg);\nx.map(|msg| log_err_msg(format_msg(msg)));\n```\n\nThe correct use would be:\n\n```rust\nlet x: Result = do_stuff();\nif let Ok(msg) = x {\n log_err_msg(msg);\n};\nif let Ok(msg) = x {\n log_err_msg(format_msg(msg));\n};\n```" + } + }, + { + "id": "reversed_empty_ranges", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for range expressions `x..y` where both `x` and `y`\nare constant and `x` is greater or equal to `y`.", + "Why is this bad": "Empty ranges yield no values so iterating them is a no-op.\nMoreover, trying to use a reversed range to index a slice will panic at run-time.", + "Known problems": "None.", + "Example": "```rust,no_run\nfn main() {\n (10..=0).for_each(|x| println!(\"{}\", x));\n\n let arr = [1, 2, 3, 4, 5];\n let sub = &arr[3..1];\n}\n```\nUse instead:\n```rust\nfn main() {\n (0..=10).rev().for_each(|x| println!(\"{}\", x));\n\n let arr = [1, 2, 3, 4, 5];\n let sub = &arr[1..3];\n}\n```" + } + }, + { + "id": "same_functions_in_if_condition", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for consecutive `if`s with the same function call.", + "Why is this bad": "This is probably a copy & paste error.\nDespite the fact that function can have side effects and `if` works as\nintended, such an approach is implicit and can be considered a \"code smell\".", + "Known problems": "Hopefully none.", + "Example": "```ignore\nif foo() == bar {\n \u2026\n} else if foo() == bar {\n \u2026\n}\n```\n\nThis probably should be:\n```ignore\nif foo() == bar {\n \u2026\n} else if foo() == baz {\n \u2026\n}\n```\n\nor if the original code was not a typo and called function mutates a state,\nconsider move the mutation out of the `if` condition to avoid similarity to\na copy & paste error:\n\n```ignore\nlet first = foo();\nif first == bar {\n \u2026\n} else {\n let second = foo();\n if second == bar {\n \u2026\n }\n}\n```" + } + }, + { + "id": "search_is_some", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for an iterator search (such as `find()`,\n`position()`, or `rposition()`) followed by a call to `is_some()`.", + "Why is this bad": "Readability, this can be written more concisely as\n`_.any(_)`.", + "Known problems": "None.", + "Example": "```rust\nvec.iter().find(|x| **x == 0).is_some();\n```\nCould be written as\n```rust\nvec.iter().any(|x| *x == 0);\n```" + } + }, + { + "id": "serde_api_misuse", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for mis-uses of the serde API.", + "Why is this bad": "Serde is very finnicky about how its API should be\nused, but the type system can't be used to enforce it (yet?).", + "Known problems": "None.", + "Example": "Implementing `Visitor::visit_string` but not\n`Visitor::visit_str`." + } + }, + { + "id": "shadow_reuse", + "group": "restriction", + "level": "Allow", + "docs": { + "What it does": "Checks for bindings that shadow other bindings already in\nscope, while reusing the original value.", + "Why is this bad": "Not too much, in fact it's a common pattern in Rust\ncode. Still, some argue that name shadowing like this hurts readability,\nbecause a value may be bound to different things depending on position in\nthe code.", + "Known problems": "This lint, as the other shadowing related lints,\ncurrently only catches very simple patterns.", + "Example": "```rust\nlet x = 2;\nlet x = x + 1;\n```\nuse different variable name:\n```rust\nlet x = 2;\nlet y = x + 1;\n```" + } + }, + { + "id": "shadow_same", + "group": "restriction", + "level": "Allow", + "docs": { + "What it does": "Checks for bindings that shadow other bindings already in\nscope, while just changing reference level or mutability.", + "Why is this bad": "Not much, in fact it's a very common pattern in Rust\ncode. Still, some may opt to avoid it in their code base, they can set this\nlint to `Warn`.", + "Known problems": "This lint, as the other shadowing related lints,\ncurrently only catches very simple patterns.", + "Example": "```rust\n\n// Bad\nlet x = &x;\n\n// Good\nlet y = &x; // use different variable name\n```" + } + }, + { + "id": "shadow_unrelated", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for bindings that shadow other bindings already in\nscope, either without a initialization or with one that does not even use\nthe original value.", + "Why is this bad": "Name shadowing can hurt readability, especially in\nlarge code bases, because it is easy to lose track of the active binding at\nany place in the code. This can be alleviated by either giving more specific\nnames to bindings or introducing more scopes to contain the bindings.", + "Known problems": "This lint, as the other shadowing related lints,\ncurrently only catches very simple patterns.", + "Example": "```rust\nlet x = y;\n\n// Bad\nlet x = z; // shadows the earlier binding\n\n// Good\nlet w = z; // use different variable name\n```" + } + }, + { + "id": "short_circuit_statement", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for the use of short circuit boolean conditions as\na\nstatement.", + "Why is this bad": "Using a short circuit boolean condition as a statement\nmay hide the fact that the second part is executed or not depending on the\noutcome of the first part.", + "Known problems": "None.", + "Example": "```rust,ignore\nf() && g(); // We should write `if f() { g(); }`.\n```" + } + }, + { + "id": "should_assert_eq", + "group": "deprecated", + "level": "Deprecated", + "docs": { + "What it does": "Nothing. This lint has been deprecated.", + "Deprecation reason": "This used to check for `assert!(a == b)` and recommend\nreplacement with `assert_eq!(a, b)`, but this is no longer needed after RFC 2011." + } + }, + { + "id": "should_implement_trait", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for methods that should live in a trait\nimplementation of a `std` trait (see [llogiq's blog\npost](http://llogiq.github.io/2015/07/30/traits.html) for further\ninformation) instead of an inherent implementation.", + "Why is this bad": "Implementing the traits improve ergonomics for users of\nthe code, often with very little cost. Also people seeing a `mul(...)`\nmethod\nmay expect `*` to work equally, so you should have good reason to disappoint\nthem.", + "Known problems": "None.", + "Example": "```rust\nstruct X;\nimpl X {\n fn add(&self, other: &X) -> X {\n // ..\n }\n}\n```" + } + }, + { + "id": "similar_names", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for names that are very similar and thus confusing.", + "Why is this bad": "It's hard to distinguish between names that differ only\nby a single character.", + "Known problems": "None?", + "Example": "```ignore\nlet checked_exp = something;\nlet checked_expr = something_else;\n```" + } + }, + { + "id": "single_char_pattern", + "group": "perf", + "level": "Warn", + "docs": { + "What it does": "Checks for string methods that receive a single-character\n`str` as an argument, e.g., `_.split(\"x\")`.", + "Why is this bad": "Performing these methods using a `char` is faster than\nusing a `str`.", + "Known problems": "Does not catch multi-byte unicode characters.", + "Example": "```rust,ignore\n// Bad\n_.split(\"x\");\n\n// Good\n_.split('x');" + } + }, + { + "id": "single_component_path_imports", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checking for imports with single component use path.", + "Why is this bad": "Import with single component use path such as `use cratename;`\nis not necessary, and thus should be removed.", + "Known problems": "None.", + "Example": "```rust,ignore\nuse regex;\n\nfn main() {\n regex::Regex::new(r\"^\\d{4}-\\d{2}-\\d{2}$\").unwrap();\n}\n```\nBetter as\n```rust,ignore\nfn main() {\n regex::Regex::new(r\"^\\d{4}-\\d{2}-\\d{2}$\").unwrap();\n}\n```" + } + }, + { + "id": "single_match", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for matches with a single arm where an `if let`\nwill usually suffice.", + "Why is this bad": "Just readability \u2013 `if let` nests less than a `match`.", + "Known problems": "None.", + "Example": "```rust\n\n// Bad\nmatch x {\n Some(ref foo) => bar(foo),\n _ => (),\n}\n\n// Good\nif let Some(ref foo) = x {\n bar(foo);\n}\n```" + } + }, + { + "id": "single_match_else", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for matches with two arms where an `if let else` will\nusually suffice.", + "Why is this bad": "Just readability \u2013 `if let` nests less than a `match`.", + "Known problems": "Personal style preferences may differ.", + "Example": "Using `match`:\n\n```rust\nmatch x {\n Some(ref foo) => bar(foo),\n _ => bar(&other_ref),\n}\n```\n\nUsing `if let` with `else`:\n\n```rust\nif let Some(ref foo) = x {\n bar(foo);\n} else {\n bar(&other_ref);\n}\n```" + } + }, + { + "id": "skip_while_next", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for usage of `_.skip_while(condition).next()`.", + "Why is this bad": "Readability, this can be written more concisely as\n`_.find(!condition)`.", + "Known problems": "None.", + "Example": "```rust\nvec.iter().skip_while(|x| **x == 0).next();\n```\nCould be written as\n```rust\nvec.iter().find(|x| **x != 0);\n```" + } + }, + { + "id": "slow_vector_initialization", + "group": "perf", + "level": "Warn", + "docs": { + "What it does": "Checks slow zero-filled vector initialization", + "Why is this bad": "These structures are non-idiomatic and less efficient than simply using\n`vec![0; len]`.", + "Known problems": "None.", + "Example": "```rust\n\n// Bad\nlet mut vec1 = Vec::with_capacity(len);\nvec1.resize(len, 0);\n\nlet mut vec2 = Vec::with_capacity(len);\nvec2.extend(repeat(0).take(len));\n\n// Good\nlet mut vec1 = vec![0; len];\nlet mut vec2 = vec![0; len];\n```" + } + }, + { + "id": "str_to_string", + "group": "deprecated", + "level": "Deprecated", + "docs": { + "What it does": "Nothing. This lint has been deprecated.", + "Deprecation reason": "This used to check for `.to_string()` method calls on values\nof type `&str`. This is not unidiomatic and with specialization coming, `to_string` could be\nspecialized to be as efficient as `to_owned`." + } + }, + { + "id": "string_add", + "group": "restriction", + "level": "Allow", + "docs": { + "What it does": "Checks for all instances of `x + _` where `x` is of type\n`String`, but only if [`string_add_assign`](#string_add_assign) does *not*\nmatch.", + "Why is this bad": "It's not bad in and of itself. However, this particular\n`Add` implementation is asymmetric (the other operand need not be `String`,\nbut `x` does), while addition as mathematically defined is symmetric, also\nthe `String::push_str(_)` function is a perfectly good replacement.\nTherefore, some dislike it and wish not to have it in their code.\n\nThat said, other people think that string addition, having a long tradition\nin other languages is actually fine, which is why we decided to make this\nparticular lint `allow` by default.", + "Known problems": "None.", + "Example": "```rust\nlet x = \"Hello\".to_owned();\nx + \", World\";\n```" + } + }, + { + "id": "string_add_assign", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for string appends of the form `x = x + y` (without\n`let`!).", + "Why is this bad": "It's not really bad, but some people think that the\n`.push_str(_)` method is more readable.", + "Known problems": "None.", + "Example": "```rust\nlet mut x = \"Hello\".to_owned();\nx = x + \", World\";\n\n// More readable\nx += \", World\";\nx.push_str(\", World\");\n```" + } + }, + { + "id": "string_extend_chars", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for the use of `.extend(s.chars())` where s is a\n`&str` or `String`.", + "Why is this bad": "`.push_str(s)` is clearer", + "Known problems": "None.", + "Example": "```rust\nlet abc = \"abc\";\nlet def = String::from(\"def\");\nlet mut s = String::new();\ns.extend(abc.chars());\ns.extend(def.chars());\n```\nThe correct use would be:\n```rust\nlet abc = \"abc\";\nlet def = String::from(\"def\");\nlet mut s = String::new();\ns.push_str(abc);\ns.push_str(&def);\n```" + } + }, + { + "id": "string_lit_as_bytes", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for the `as_bytes` method called on string literals\nthat contain only ASCII characters.", + "Why is this bad": "Byte string literals (e.g., `b\"foo\"`) can be used\ninstead. They are shorter but less discoverable than `as_bytes()`.", + "Known Problems": "None.", + "Example": "```rust\n// Bad\nlet bs = \"a byte string\".as_bytes();\n\n// Good\nlet bs = b\"a byte string\";\n```" + } + }, + { + "id": "string_to_string", + "group": "deprecated", + "level": "Deprecated", + "docs": { + "What it does": "Nothing. This lint has been deprecated.", + "Deprecation reason": "This used to check for `.to_string()` method calls on values\nof type `String`. This is not unidiomatic and with specialization coming, `to_string` could be\nspecialized to be as efficient as `clone`." + } + }, + { + "id": "struct_excessive_bools", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for excessive\nuse of bools in structs.", + "Why is this bad": "Excessive bools in a struct\nis often a sign that it's used as a state machine,\nwhich is much better implemented as an enum.\nIf it's not the case, excessive bools usually benefit\nfrom refactoring into two-variant enums for better\nreadability and API.", + "Known problems": "None.", + "Example": "Bad:\n```rust\nstruct S {\n is_pending: bool,\n is_processing: bool,\n is_finished: bool,\n}\n```\n\nGood:\n```rust\nenum S {\n Pending,\n Processing,\n Finished,\n}\n```", + "Configuration": "This lint has the following configuration variables:\n\n* `max-struct-bools: u64`: The maximum number of bools a struct can have (defaults to `3`)." + } + }, + { + "id": "suboptimal_flops", + "group": "nursery", + "level": "Allow", + "docs": { + "What it does": "Looks for floating-point expressions that\ncan be expressed using built-in methods to improve both\naccuracy and performance.", + "Why is this bad": "Negatively impacts accuracy and performance.", + "Known problems": "None", + "Example": "```rust\nuse std::f32::consts::E;\n\nlet a = 3f32;\nlet _ = (2f32).powf(a);\nlet _ = E.powf(a);\nlet _ = a.powf(1.0 / 2.0);\nlet _ = a.log(2.0);\nlet _ = a.log(10.0);\nlet _ = a.log(E);\nlet _ = a.powf(2.0);\nlet _ = a * 2.0 + 4.0;\nlet _ = if a < 0.0 {\n -a\n} else {\n a\n};\nlet _ = if a < 0.0 {\n a\n} else {\n -a\n};\n```\n\nis better expressed as\n\n```rust\nuse std::f32::consts::E;\n\nlet a = 3f32;\nlet _ = a.exp2();\nlet _ = a.exp();\nlet _ = a.sqrt();\nlet _ = a.log2();\nlet _ = a.log10();\nlet _ = a.ln();\nlet _ = a.powi(2);\nlet _ = a.mul_add(2.0, 4.0);\nlet _ = a.abs();\nlet _ = -a.abs();\n```" + } + }, + { + "id": "suspicious_arithmetic_impl", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Lints for suspicious operations in impls of arithmetic operators, e.g.\nsubtracting elements in an Add impl.", + "Why this is bad": "This is probably a typo or copy-and-paste error and not intended.", + "Known problems": "None.", + "Example": "```ignore\nimpl Add for Foo {\n type Output = Foo;\n\n fn add(self, other: Foo) -> Foo {\n Foo(self.0 - other.0)\n }\n}\n```" + } + }, + { + "id": "suspicious_assignment_formatting", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for use of the non-existent `=*`, `=!` and `=-`\noperators.", + "Why is this bad": "This is either a typo of `*=`, `!=` or `-=` or\nconfusing.", + "Known problems": "None.", + "Example": "```rust,ignore\na =- 42; // confusing, should it be `a -= 42` or `a = -42`?\n```" + } + }, + { + "id": "suspicious_else_formatting", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for formatting of `else`. It lints if the `else`\nis followed immediately by a newline or the `else` seems to be missing.", + "Why is this bad": "This is probably some refactoring remnant, even if the\ncode is correct, it might look confusing.", + "Known problems": "None.", + "Example": "```rust,ignore\nif foo {\n} { // looks like an `else` is missing here\n}\n\nif foo {\n} if bar { // looks like an `else` is missing here\n}\n\nif foo {\n} else\n\n{ // this is the `else` block of the previous `if`, but should it be?\n}\n\nif foo {\n} else\n\nif bar { // this is the `else` block of the previous `if`, but should it be?\n}\n```" + } + }, + { + "id": "suspicious_map", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for calls to `map` followed by a `count`.", + "Why is this bad": "It looks suspicious. Maybe `map` was confused with `filter`.\nIf the `map` call is intentional, this should be rewritten. Or, if you intend to\ndrive the iterator to completion, you can just use `for_each` instead.", + "Known problems": "None", + "Example": "```rust\nlet _ = (0..3).map(|x| x + 2).count();\n```" + } + }, + { + "id": "suspicious_op_assign_impl", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Lints for suspicious operations in impls of OpAssign, e.g.\nsubtracting elements in an AddAssign impl.", + "Why this is bad": "This is probably a typo or copy-and-paste error and not intended.", + "Known problems": "None.", + "Example": "```ignore\nimpl AddAssign for Foo {\n fn add_assign(&mut self, other: Foo) {\n *self = *self - other;\n }\n}\n```" + } + }, + { + "id": "suspicious_unary_op_formatting", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks the formatting of a unary operator on the right hand side\nof a binary operator. It lints if there is no space between the binary and unary operators,\nbut there is a space between the unary and its operand.", + "Why is this bad": "This is either a typo in the binary operator or confusing.", + "Known problems": "None.", + "Example": "```rust,ignore\nif foo <- 30 { // this should be `foo < -30` but looks like a different operator\n}\n\nif foo &&! bar { // this should be `foo && !bar` but looks like a different operator\n}\n```" + } + }, + { + "id": "tabs_in_doc_comments", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks doc comments for usage of tab characters.", + "Why is this bad": "The rust style-guide promotes spaces instead of tabs for indentation.\nTo keep a consistent view on the source, also doc comments should not have tabs.\nAlso, explaining ascii-diagrams containing tabs can get displayed incorrectly when the\ndisplay settings of the author and reader differ.", + "Known problems": "None.", + "Example": "```rust\n///\n/// Struct to hold two strings:\n/// \t- first\t\tone\n/// \t- second\tone\npub struct DoubleString {\n ///\n /// \t- First String:\n /// \t\t- needs to be inside here\n first_string: String,\n ///\n /// \t- Second String:\n /// \t\t- needs to be inside here\n second_string: String,\n}\n```\n\nWill be converted to:\n```rust\n///\n/// Struct to hold two strings:\n/// - first one\n/// - second one\npub struct DoubleString {\n ///\n /// - First String:\n /// - needs to be inside here\n first_string: String,\n ///\n /// - Second String:\n /// - needs to be inside here\n second_string: String,\n}\n```" + } + }, + { + "id": "temporary_assignment", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for construction of a structure or tuple just to\nassign a value in it.", + "Why is this bad": "Readability. If the structure is only created to be\nupdated, why not write the structure you want in the first place?", + "Known problems": "None.", + "Example": "```rust\n(0, 0).0 = 1\n```" + } + }, + { + "id": "temporary_cstring_as_ptr", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for getting the inner pointer of a temporary\n`CString`.", + "Why is this bad": "The inner pointer of a `CString` is only valid as long\nas the `CString` is alive.", + "Known problems": "None.", + "Example": "```rust\n#\nlet c_str = CString::new(\"foo\").unwrap().as_ptr();\nunsafe {\n call_some_ffi_func(c_str);\n}\n```\nHere `c_str` point to a freed address. The correct use would be:\n```rust\n#\nlet c_str = CString::new(\"foo\").unwrap();\nunsafe {\n call_some_ffi_func(c_str.as_ptr());\n}\n```" + } + }, + { + "id": "to_digit_is_some", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for `.to_digit(..).is_some()` on `char`s.", + "Why is this bad": "This is a convoluted way of checking if a `char` is a digit. It's\nmore straight forward to use the dedicated `is_digit` method.", + "Example": "```rust\nlet is_digit = c.to_digit(radix).is_some();\n```\ncan be written as:\n```\n# let c = 'c';\n# let radix = 10;\nlet is_digit = c.is_digit(radix);\n```" + } + }, + { + "id": "todo", + "group": "restriction", + "level": "Allow", + "docs": { + "What it does": "Checks for usage of `todo!`.", + "Why is this bad": "This macro should not be present in production code", + "Known problems": "None.", + "Example": "```no_run\ntodo!();\n```" + } + }, + { + "id": "too_many_arguments", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for functions with too many parameters.", + "Why is this bad": "Functions with lots of parameters are considered bad\nstyle and reduce readability (\u201cwhat does the 5th parameter mean?\u201d). Consider\ngrouping some parameters into a new type.", + "Known problems": "None.", + "Example": "```rust\nfn foo(x: u32, y: u32, name: &str, c: Color, w: f32, h: f32, a: f32, b: f32) {\n // ..\n}\n```", + "Configuration": "This lint has the following configuration variables:\n\n* `too-many-arguments-threshold: u64`: The maximum number of argument a function or method can have (defaults to `7`)." + } + }, + { + "id": "too_many_lines", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for functions with a large amount of lines.", + "Why is this bad": "Functions with a lot of lines are harder to understand\ndue to having to look at a larger amount of code to understand what the\nfunction is doing. Consider splitting the body of the function into\nmultiple functions.", + "Known problems": "None.", + "Example": "```rust\nfn im_too_long() {\n println!(\"\");\n // ... 100 more LoC\n println!(\"\");\n}\n```", + "Configuration": "This lint has the following configuration variables:\n\n* `too-many-lines-threshold: u64`: The maximum number of lines a function or method can have (defaults to `100`)." + } + }, + { + "id": "toplevel_ref_arg", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for function arguments and let bindings denoted as\n`ref`.", + "Why is this bad": "The `ref` declaration makes the function take an owned\nvalue, but turns the argument into a reference (which means that the value\nis destroyed when exiting the function). This adds not much value: either\ntake a reference type, or take an owned value and create references in the\nbody.\n\nFor let bindings, `let x = &foo;` is preferred over `let ref x = foo`. The\ntype of `x` is more obvious with the former.", + "Known problems": "If the argument is dereferenced within the function,\nremoving the `ref` will lead to errors. This can be fixed by removing the\ndereferences, e.g., changing `*x` to `x` within the function.", + "Example": "```rust,ignore\n// Bad\nfn foo(ref x: u8) -> bool {\n true\n}\n\n// Good\nfn foo(x: &u8) -> bool {\n true\n}\n```" + } + }, + { + "id": "transmute_bytes_to_str", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for transmutes from a `&[u8]` to a `&str`.", + "Why is this bad": "Not every byte slice is a valid UTF-8 string.", + "Known problems": "- [`from_utf8`] which this lint suggests using is slower than `transmute`\nas it needs to validate the input.\nIf you are certain that the input is always a valid UTF-8,\nuse [`from_utf8_unchecked`] which is as fast as `transmute`\nbut has a semantically meaningful name.\n- You might want to handle errors returned from [`from_utf8`] instead of calling `unwrap`.\n\n[`from_utf8`]: https://doc.rust-lang.org/std/str/fn.from_utf8.html\n[`from_utf8_unchecked`]: https://doc.rust-lang.org/std/str/fn.from_utf8_unchecked.html", + "Example": "```rust\nlet b: &[u8] = &[1_u8, 2_u8];\nunsafe {\n let _: &str = std::mem::transmute(b); // where b: &[u8]\n}\n\n// should be:\nlet _ = std::str::from_utf8(b).unwrap();\n```" + } + }, + { + "id": "transmute_float_to_int", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for transmutes from a float to an integer.", + "Why is this bad": "Transmutes are dangerous and error-prone, whereas `to_bits` is intuitive\nand safe.", + "Known problems": "None.", + "Example": "```rust\nunsafe {\n let _: u32 = std::mem::transmute(1f32);\n}\n\n// should be:\nlet _: u32 = 1f32.to_bits();\n```" + } + }, + { + "id": "transmute_int_to_bool", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for transmutes from an integer to a `bool`.", + "Why is this bad": "This might result in an invalid in-memory representation of a `bool`.", + "Known problems": "None.", + "Example": "```rust\nlet x = 1_u8;\nunsafe {\n let _: bool = std::mem::transmute(x); // where x: u8\n}\n\n// should be:\nlet _: bool = x != 0;\n```" + } + }, + { + "id": "transmute_int_to_char", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for transmutes from an integer to a `char`.", + "Why is this bad": "Not every integer is a Unicode scalar value.", + "Known problems": "- [`from_u32`] which this lint suggests using is slower than `transmute`\nas it needs to validate the input.\nIf you are certain that the input is always a valid Unicode scalar value,\nuse [`from_u32_unchecked`] which is as fast as `transmute`\nbut has a semantically meaningful name.\n- You might want to handle `None` returned from [`from_u32`] instead of calling `unwrap`.\n\n[`from_u32`]: https://doc.rust-lang.org/std/char/fn.from_u32.html\n[`from_u32_unchecked`]: https://doc.rust-lang.org/std/char/fn.from_u32_unchecked.html", + "Example": "```rust\nlet x = 1_u32;\nunsafe {\n let _: char = std::mem::transmute(x); // where x: u32\n}\n\n// should be:\nlet _ = std::char::from_u32(x).unwrap();\n```" + } + }, + { + "id": "transmute_int_to_float", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for transmutes from an integer to a float.", + "Why is this bad": "Transmutes are dangerous and error-prone, whereas `from_bits` is intuitive\nand safe.", + "Known problems": "None.", + "Example": "```rust\nunsafe {\n let _: f32 = std::mem::transmute(1_u32); // where x: u32\n}\n\n// should be:\nlet _: f32 = f32::from_bits(1_u32);\n```" + } + }, + { + "id": "transmute_ptr_to_ptr", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for transmutes from a pointer to a pointer, or\nfrom a reference to a reference.", + "Why is this bad": "Transmutes are dangerous, and these can instead be\nwritten as casts.", + "Known problems": "None.", + "Example": "```rust\nlet ptr = &1u32 as *const u32;\nunsafe {\n // pointer-to-pointer transmute\n let _: *const f32 = std::mem::transmute(ptr);\n // ref-ref transmute\n let _: &f32 = std::mem::transmute(&1u32);\n}\n// These can be respectively written:\nlet _ = ptr as *const f32;\nlet _ = unsafe{ &*(&1u32 as *const u32 as *const f32) };\n```" + } + }, + { + "id": "transmute_ptr_to_ref", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for transmutes from a pointer to a reference.", + "Why is this bad": "This can always be rewritten with `&` and `*`.", + "Known problems": "None.", + "Example": "```rust,ignore\nunsafe {\n let _: &T = std::mem::transmute(p); // where p: *const T\n}\n\n// can be written:\nlet _: &T = &*p;\n```" + } + }, + { + "id": "transmuting_null", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for transmute calls which would receive a null pointer.", + "Why is this bad": "Transmuting a null pointer is undefined behavior.", + "Known problems": "Not all cases can be detected at the moment of this writing.\nFor example, variables which hold a null pointer and are then fed to a `transmute`\ncall, aren't detectable yet.", + "Example": "```rust\nlet null_ref: &u64 = unsafe { std::mem::transmute(0 as *const u64) };\n```" + } + }, + { + "id": "trivial_regex", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for trivial [regex](https://crates.io/crates/regex)\ncreation (with `Regex::new`, `RegexBuilder::new` or `RegexSet::new`).", + "Why is this bad": "Matching the regex can likely be replaced by `==` or\n`str::starts_with`, `str::ends_with` or `std::contains` or other `str`\nmethods.", + "Known problems": "None.", + "Example": "```ignore\nRegex::new(\"^foobar\")\n```" + } + }, + { + "id": "trivially_copy_pass_by_ref", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for functions taking arguments by reference, where\nthe argument type is `Copy` and small enough to be more efficient to always\npass by value.", + "Why is this bad": "In many calling conventions instances of structs will\nbe passed through registers if they fit into two or less general purpose\nregisters.", + "Known problems": "This lint is target register size dependent, it is\nlimited to 32-bit to try and reduce portability problems between 32 and\n64-bit, but if you are compiling for 8 or 16-bit targets then the limit\nwill be different.\n\nThe configuration option `trivial_copy_size_limit` can be set to override\nthis limit for a project.\n\nThis lint attempts to allow passing arguments by reference if a reference\nto that argument is returned. This is implemented by comparing the lifetime\nof the argument and return value for equality. However, this can cause\nfalse positives in cases involving multiple lifetimes that are bounded by\neach other.", + "Example": "```rust\n// Bad\nfn foo(v: &u32) {}\n```\n\n```rust\n// Better\nfn foo(v: u32) {}\n```", + "Configuration": "This lint has the following configuration variables:\n\n* `trivial-copy-size-limit: Option`: The maximum size (in bytes) to consider a `Copy` type for passing by value instead of by reference. (defaults to `None`)." + } + }, + { + "id": "try_err", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for usages of `Err(x)?`.", + "Why is this bad": "The `?` operator is designed to allow calls that\ncan fail to be easily chained. For example, `foo()?.bar()` or\n`foo(bar()?)`. Because `Err(x)?` can't be used that way (it will\nalways return), it is more clear to write `return Err(x)`.", + "Known problems": "None.", + "Example": "```rust\nfn foo(fail: bool) -> Result {\n if fail {\n Err(\"failed\")?;\n }\n Ok(0)\n}\n```\nCould be written:\n\n```rust\nfn foo(fail: bool) -> Result {\n if fail {\n return Err(\"failed\".into());\n }\n Ok(0)\n}\n```" + } + }, + { + "id": "type_complexity", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for types used in structs, parameters and `let`\ndeclarations above a certain complexity threshold.", + "Why is this bad": "Too complex types make the code less readable. Consider\nusing a `type` definition to simplify them.", + "Known problems": "None.", + "Example": "```rust\nstruct Foo {\n inner: Rc>>>,\n}\n```", + "Configuration": "This lint has the following configuration variables:\n\n* `type-complexity-threshold: u64`: The maximum complexity a type can have (defaults to `250`)." + } + }, + { + "id": "type_repetition_in_bounds", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "This lint warns about unnecessary type repetitions in trait bounds", + "Why is this bad": "Repeating the type for every bound makes the code\nless readable than combining the bounds", + "Example": "```rust\npub fn foo(t: T) where T: Copy, T: Clone {}\n```\n\nCould be written as:\n\n```rust\npub fn foo(t: T) where T: Copy + Clone {}\n```" + } + }, + { + "id": "unicode_not_nfc", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for string literals that contain Unicode in a form\nthat is not equal to its\n[NFC-recomposition](http://www.unicode.org/reports/tr15/#Norm_Forms).", + "Why is this bad": "If such a string is compared to another, the results\nmay be surprising.", + "Known problems": "None.", + "Example": "You may not see it, but \"a\u0300\"\" and \"\u00e0\"\" aren't the same string. The\nformer when escaped is actually `\"a\\u{300}\"` while the latter is `\"\\u{e0}\"`." + } + }, + { + "id": "unimplemented", + "group": "restriction", + "level": "Allow", + "docs": { + "What it does": "Checks for usage of `unimplemented!`.", + "Why is this bad": "This macro should not be present in production code", + "Known problems": "None.", + "Example": "```no_run\nunimplemented!();\n```" + } + }, + { + "id": "uninit_assumed_init", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for `MaybeUninit::uninit().assume_init()`.", + "Why is this bad": "For most types, this is undefined behavior.", + "Known problems": "For now, we accept empty tuples and tuples / arrays\nof `MaybeUninit`. There may be other types that allow uninitialized\ndata, but those are not yet rigorously defined.", + "Example": "```rust\n// Beware the UB\nuse std::mem::MaybeUninit;\n\nlet _: usize = unsafe { MaybeUninit::uninit().assume_init() };\n```\n\nNote that the following is OK:\n\n```rust\nuse std::mem::MaybeUninit;\n\nlet _: [MaybeUninit; 5] = unsafe {\n MaybeUninit::uninit().assume_init()\n};\n```" + } + }, + { + "id": "unit_arg", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for passing a unit value as an argument to a function without using a\nunit literal (`()`).", + "Why is this bad": "This is likely the result of an accidental semicolon.", + "Known problems": "None.", + "Example": "```rust,ignore\nfoo({\n let a = bar();\n baz(a);\n})\n```" + } + }, + { + "id": "unit_cmp", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for comparisons to unit. This includes all binary\ncomparisons (like `==` and `<`) and asserts.", + "Why is this bad": "Unit is always equal to itself, and thus is just a\nclumsily written constant. Mostly this happens when someone accidentally\nadds semicolons at the end of the operands.", + "Known problems": "None.", + "Example": "```rust\nif {\n foo();\n} == {\n bar();\n} {\n baz();\n}\n```\nis equal to\n```rust\n{\n foo();\n bar();\n baz();\n}\n```\n\nFor asserts:\n```rust\nassert_eq!({ foo(); }, { bar(); });\n```\nwill always succeed" + } + }, + { + "id": "unknown_clippy_lints", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for `allow`/`warn`/`deny`/`forbid` attributes with scoped clippy\nlints and if those lints exist in clippy. If there is an uppercase letter in the lint name\n(not the tool name) and a lowercase version of this lint exists, it will suggest to lowercase\nthe lint name.", + "Why is this bad": "A lint attribute with a mistyped lint name won't have an effect.", + "Known problems": "None.", + "Example": "Bad:\n```rust\n#![warn(if_not_els)]\n#![deny(clippy::All)]\n```\n\nGood:\n```rust\n#![warn(if_not_else)]\n#![deny(clippy::all)]\n```" + } + }, + { + "id": "unnecessary_cast", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for casts to the same type.", + "Why is this bad": "It's just unnecessary.", + "Known problems": "None.", + "Example": "```rust\nlet _ = 2i32 as i32;\n```" + } + }, + { + "id": "unnecessary_filter_map", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for `filter_map` calls which could be replaced by `filter` or `map`.\nMore specifically it checks if the closure provided is only performing one of the\nfilter or map operations and suggests the appropriate option.", + "Why is this bad": "Complexity. The intent is also clearer if only a single\noperation is being performed.", + "Known problems": "None", + "Example": "```rust\nlet _ = (0..3).filter_map(|x| if x > 2 { Some(x) } else { None });\n\n// As there is no transformation of the argument this could be written as:\nlet _ = (0..3).filter(|&x| x > 2);\n```\n\n```rust\nlet _ = (0..4).filter_map(|x| Some(x + 1));\n\n// As there is no conditional check on the argument this could be written as:\nlet _ = (0..4).map(|x| x + 1);\n```" + } + }, + { + "id": "unnecessary_fold", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for using `fold` when a more succinct alternative exists.\nSpecifically, this checks for `fold`s which could be replaced by `any`, `all`,\n`sum` or `product`.", + "Why is this bad": "Readability.", + "Known problems": "False positive in pattern guards. Will be resolved once\nnon-lexical lifetimes are stable.", + "Example": "```rust\nlet _ = (0..3).fold(false, |acc, x| acc || x > 2);\n```\nThis could be written as:\n```rust\nlet _ = (0..3).any(|x| x > 2);\n```" + } + }, + { + "id": "unnecessary_mut_passed", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Detects passing a mutable reference to a function that only\nrequires an immutable reference.", + "Why is this bad": "The immutable reference rules out all other references\nto the value. Also the code misleads about the intent of the call site.", + "Known problems": "None.", + "Example": "```ignore\n// Bad\nmy_vec.push(&mut value)\n\n// Good\nmy_vec.push(&value)\n```" + } + }, + { + "id": "unnecessary_operation", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for expression statements that can be reduced to a\nsub-expression.", + "Why is this bad": "Expressions by themselves often have no side-effects.\nHaving such expressions reduces readability.", + "Known problems": "None.", + "Example": "```rust,ignore\ncompute_array()[0];\n```" + } + }, + { + "id": "unnecessary_sort_by", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Detects when people use `Vec::sort_by` and pass in a function\nwhich compares the two arguments, either directly or indirectly.", + "Why is this bad": "It is more clear to use `Vec::sort_by_key` (or `Vec::sort` if\npossible) than to use `Vec::sort_by` and and a more complicated\nclosure.", + "Known problems": "If the suggested `Vec::sort_by_key` uses Reverse and it isn't\nimported by a use statement in the current frame, then a `use`\nstatement that imports it will need to be added (which this lint\ncan't do).", + "Example": "```rust\nvec.sort_by(|a, b| a.foo().cmp(&b.foo()));\n```\nUse instead:\n```rust\nvec.sort_by_key(|a| a.foo());\n```" + } + }, + { + "id": "unnecessary_unwrap", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for calls of `unwrap[_err]()` that cannot fail.", + "Why is this bad": "Using `if let` or `match` is more idiomatic.", + "Known problems": "None", + "Example": "```rust\nif option.is_some() {\n do_something_with(option.unwrap())\n}\n```\n\nCould be written:\n\n```rust\nif let Some(value) = option {\n do_something_with(value)\n}\n```" + } + }, + { + "id": "unneeded_field_pattern", + "group": "restriction", + "level": "Allow", + "docs": { + "What it does": "Checks for structure field patterns bound to wildcards.", + "Why is this bad": "Using `..` instead is shorter and leaves the focus on\nthe fields that are actually bound.", + "Known problems": "None.", + "Example": "```rust\nlet f = Foo { a: 0, b: 0, c: 0 };\n\n// Bad\nmatch f {\n Foo { a: _, b: 0, .. } => {},\n Foo { a: _, b: _, c: _ } => {},\n}\n\n// Good\nmatch f {\n Foo { b: 0, .. } => {},\n Foo { .. } => {},\n}\n```" + } + }, + { + "id": "unneeded_wildcard_pattern", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for tuple patterns with a wildcard\npattern (`_`) is next to a rest pattern (`..`).\n\n_NOTE_: While `_, ..` means there is at least one element left, `..`\nmeans there are 0 or more elements left. This can make a difference\nwhen refactoring, but shouldn't result in errors in the refactored code,\nsince the wildcard pattern isn't used anyway.", + "Why is this bad": "The wildcard pattern is unneeded as the rest pattern\ncan match that element as well.", + "Known problems": "None.", + "Example": "```rust\n\n// Bad\nmatch t {\n TupleStruct(0, .., _) => (),\n _ => (),\n}\n\n// Good\nmatch t {\n TupleStruct(0, ..) => (),\n _ => (),\n}\n```" + } + }, + { + "id": "unnested_or_patterns", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for unnested or-patterns, e.g., `Some(0) | Some(2)` and\nsuggests replacing the pattern with a nested one, `Some(0 | 2)`.\n\nAnother way to think of this is that it rewrites patterns in\n*disjunctive normal form (DNF)* into *conjunctive normal form (CNF)*.", + "Why is this bad": "In the example above, `Some` is repeated, which unncessarily complicates the pattern.", + "Known problems": "None.", + "Example": "```rust\nfn main() {\n if let Some(0) | Some(2) = Some(0) {}\n}\n```\nUse instead:\n```rust\n#![feature(or_patterns)]\n\nfn main() {\n if let Some(0 | 2) = Some(0) {}\n}\n```" + } + }, + { + "id": "unreachable", + "group": "restriction", + "level": "Allow", + "docs": { + "What it does": "Checks for usage of `unreachable!`.", + "Why is this bad": "This macro can cause code to panic", + "Known problems": "None.", + "Example": "```no_run\nunreachable!();\n```" + } + }, + { + "id": "unreadable_literal", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Warns if a long integral or floating-point constant does\nnot contain underscores.", + "Why is this bad": "Reading long numbers is difficult without separators.", + "Known problems": "None.", + "Example": "```rust\n// Bad\nlet x: u64 = 61864918973511;\n\n// Good\nlet x: u64 = 61_864_918_973_511;\n```" + } + }, + { + "id": "unsafe_derive_deserialize", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for deriving `serde::Deserialize` on a type that\nhas methods using `unsafe`.", + "Why is this bad": "Deriving `serde::Deserialize` will create a constructor\nthat may violate invariants hold by another constructor.", + "Known problems": "None.", + "Example": "```rust,ignore\nuse serde::Deserialize;\n\n#[derive(Deserialize)]\npub struct Foo {\n // ..\n}\n\nimpl Foo {\n pub fn new() -> Self {\n // setup here ..\n }\n\n pub unsafe fn parts() -> (&str, &str) {\n // assumes invariants hold\n }\n}\n```" + } + }, + { + "id": "unsafe_removed_from_name", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for imports that remove \"unsafe\" from an item's\nname.", + "Why is this bad": "Renaming makes it less clear which traits and\nstructures are unsafe.", + "Known problems": "None.", + "Example": "```rust,ignore\nuse std::cell::{UnsafeCell as TotallySafeCell};\n\nextern crate crossbeam;\nuse crossbeam::{spawn_unsafe as spawn};\n```" + } + }, + { + "id": "unsafe_vector_initialization", + "group": "deprecated", + "level": "Deprecated", + "docs": { + "What it does": "Nothing. This lint has been deprecated.", + "Deprecation reason": "This lint used to suggest replacing `let mut vec =\nVec::with_capacity(n); vec.set_len(n);` with `let vec = vec![0; n];`. The\nreplacement has very different performance characteristics so the lint is\ndeprecated." + } + }, + { + "id": "unseparated_literal_suffix", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Warns if literal suffixes are not separated by an\nunderscore.", + "Why is this bad": "It is much less readable.", + "Known problems": "None.", + "Example": "```rust\n// Bad\nlet y = 123832i32;\n\n// Good\nlet y = 123832_i32;\n```" + } + }, + { + "id": "unsound_collection_transmute", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for transmutes between collections whose\ntypes have different ABI, size or alignment.", + "Why is this bad": "This is undefined behavior.", + "Known problems": "Currently, we cannot know whether a type is a\ncollection, so we just lint the ones that come with `std`.", + "Example": "```rust\n// different size, therefore likely out-of-bounds memory access\n// You absolutely do not want this in your code!\nunsafe {\n std::mem::transmute::<_, Vec>(vec![2_u16])\n};\n```\n\nYou must always iterate, map and collect the values:\n\n```rust\nvec![2_u16].into_iter().map(u32::from).collect::>();\n```" + } + }, + { + "id": "unstable_as_mut_slice", + "group": "deprecated", + "level": "Deprecated", + "docs": { + "What it does": "Nothing. This lint has been deprecated.", + "Deprecation reason": "This used to check for `Vec::as_mut_slice`, which was unstable with good\nstable alternatives. `Vec::as_mut_slice` has now been stabilized." + } + }, + { + "id": "unstable_as_slice", + "group": "deprecated", + "level": "Deprecated", + "docs": { + "What it does": "Nothing. This lint has been deprecated.", + "Deprecation reason": "This used to check for `Vec::as_slice`, which was unstable with good\nstable alternatives. `Vec::as_slice` has now been stabilized." + } + }, + { + "id": "unused_collect", + "group": "deprecated", + "level": "Deprecated", + "docs": { + "What it does": "Nothing. This lint has been deprecated.", + "Deprecation reason": "This lint has been superseded by #[must_use] in rustc." + } + }, + { + "id": "unused_io_amount", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for unused written/read amount.", + "Why is this bad": "`io::Write::write(_vectored)` and\n`io::Read::read(_vectored)` are not guaranteed to\nprocess the entire buffer. They return how many bytes were processed, which\nmight be smaller\nthan a given buffer's length. If you don't need to deal with\npartial-write/read, use\n`write_all`/`read_exact` instead.", + "Known problems": "Detects only common patterns.", + "Example": "```rust,ignore\nuse std::io;\nfn foo(w: &mut W) -> io::Result<()> {\n // must be `w.write_all(b\"foo\")?;`\n w.write(b\"foo\")?;\n Ok(())\n}\n```" + } + }, + { + "id": "unused_label", + "group": "deprecated", + "level": "Deprecated", + "docs": { + "What it does": "Nothing. This lint has been deprecated.", + "Deprecation reason": "This lint has been uplifted to rustc and is now called\n`unused_labels`." + } + }, + { + "id": "unused_self", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks methods that contain a `self` argument but don't use it", + "Why is this bad": "It may be clearer to define the method as an associated function instead\nof an instance method if it doesn't require `self`.", + "Known problems": "None.", + "Example": "```rust,ignore\nstruct A;\nimpl A {\n fn method(&self) {}\n}\n```\n\nCould be written:\n\n```rust,ignore\nstruct A;\nimpl A {\n fn method() {}\n}\n```" + } + }, + { + "id": "unused_unit", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for unit (`()`) expressions that can be removed.", + "Why is this bad": "Such expressions add no value, but can make the code\nless readable. Depending on formatting they can make a `break` or `return`\nstatement look like a function call.", + "Known problems": "The lint currently misses unit return types in types,\ne.g., the `F` in `fn generic_unit ()>(f: F) { .. }`.", + "Example": "```rust\nfn return_unit() -> () {\n ()\n}\n```" + } + }, + { + "id": "unwrap_used", + "group": "restriction", + "level": "Allow", + "docs": { + "What it does": "Checks for `.unwrap()` calls on `Option`s and on `Result`s.", + "Why is this bad": "It is better to handle the `None` or `Err` case,\nor at least call `.expect(_)` with a more helpful message. Still, for a lot of\nquick-and-dirty code, `unwrap` is a good choice, which is why this lint is\n`Allow` by default.\n\n`result.unwrap()` will let the thread panic on `Err` values.\nNormally, you want to implement more sophisticated error handling,\nand propagate errors upwards with `?` operator.\n\nEven if you want to panic on errors, not all `Error`s implement good\nmessages on display. Therefore, it may be beneficial to look at the places\nwhere they may get displayed. Activate this lint to do just that.", + "Known problems": "None.", + "Examples": "```rust\n\n// Bad\nopt.unwrap();\n\n// Good\nopt.expect(\"more helpful message\");\n```\n\n// or\n\n```rust\n\n// Bad\nres.unwrap();\n\n// Good\nres.expect(\"more helpful message\");\n```" + } + }, + { + "id": "use_debug", + "group": "restriction", + "level": "Allow", + "docs": { + "What it does": "Checks for use of `Debug` formatting. The purpose of this\nlint is to catch debugging remnants.", + "Why is this bad": "The purpose of the `Debug` trait is to facilitate\ndebugging Rust code. It should not be used in user-facing output.", + "Example": "```rust\nprintln!(\"{:?}\", foo);\n```" + } + }, + { + "id": "use_self", + "group": "nursery", + "level": "Allow", + "docs": { + "What it does": "Checks for unnecessary repetition of structure name when a\nreplacement with `Self` is applicable.", + "Why is this bad": "Unnecessary repetition. Mixed use of `Self` and struct\nname\nfeels inconsistent.", + "Known problems": "- False positive when using associated types (#2843)\n- False positives in some situations when using generics (#3410)", + "Example": "```rust\nstruct Foo {}\nimpl Foo {\n fn new() -> Foo {\n Foo {}\n }\n}\n```\ncould be\n```rust\nstruct Foo {}\nimpl Foo {\n fn new() -> Self {\n Self {}\n }\n}\n```" + } + }, + { + "id": "used_underscore_binding", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for the use of bindings with a single leading\nunderscore.", + "Why is this bad": "A single leading underscore is usually used to indicate\nthat a binding will not be used. Using such a binding breaks this\nexpectation.", + "Known problems": "The lint does not work properly with desugaring and\nmacro, it has been allowed in the mean time.", + "Example": "```rust\nlet _x = 0;\nlet y = _x + 1; // Here we are using `_x`, even though it has a leading\n // underscore. We should rename `_x` to `x`\n```" + } + }, + { + "id": "useless_asref", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for usage of `.as_ref()` or `.as_mut()` where the\ntypes before and after the call are the same.", + "Why is this bad": "The call is unnecessary.", + "Known problems": "None.", + "Example": "```rust\nlet x: &[i32] = &[1, 2, 3, 4, 5];\ndo_stuff(x.as_ref());\n```\nThe correct use would be:\n```rust\nlet x: &[i32] = &[1, 2, 3, 4, 5];\ndo_stuff(x);\n```" + } + }, + { + "id": "useless_attribute", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for `extern crate` and `use` items annotated with\nlint attributes.\n\nThis lint whitelists `#[allow(unused_imports)]`, `#[allow(deprecated)]` and\n`#[allow(unreachable_pub)]` on `use` items and `#[allow(unused_imports)]` on\n`extern crate` items with a `#[macro_use]` attribute.", + "Why is this bad": "Lint attributes have no effect on crate imports. Most\nlikely a `!` was forgotten.", + "Known problems": "None.", + "Example": "```ignore\n// Bad\n#[deny(dead_code)]\nextern crate foo;\n#[forbid(dead_code)]\nuse foo::bar;\n\n// Ok\n#[allow(unused_imports)]\nuse foo::baz;\n#[allow(unused_imports)]\n#[macro_use]\nextern crate baz;\n```" + } + }, + { + "id": "useless_conversion", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for `Into`, `TryInto`, `From`, `TryFrom`,`IntoIter` calls\nthat useless converts to the same type as caller.", + "Why is this bad": "Redundant code.", + "Known problems": "None.", + "Example": "```rust\n// Bad\n// format!() returns a `String`\nlet s: String = format!(\"hello\").into();\n\n// Good\nlet s: String = format!(\"hello\");\n```" + } + }, + { + "id": "useless_format", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for the use of `format!(\"string literal with no\nargument\")` and `format!(\"{}\", foo)` where `foo` is a string.", + "Why is this bad": "There is no point of doing that. `format!(\"foo\")` can\nbe replaced by `\"foo\".to_owned()` if you really need a `String`. The even\nworse `&format!(\"foo\")` is often encountered in the wild. `format!(\"{}\",\nfoo)` can be replaced by `foo.clone()` if `foo: String` or `foo.to_owned()`\nif `foo: &str`.", + "Known problems": "None.", + "Examples": "```rust\n\n// Bad\nformat!(\"{}\", foo);\n\n// Good\nformat!(\"foo\");\n```" + } + }, + { + "id": "useless_let_if_seq", + "group": "nursery", + "level": "Allow", + "docs": { + "What it does": "Checks for variable declarations immediately followed by a\nconditional affectation.", + "Why is this bad": "This is not idiomatic Rust.", + "Known problems": "None.", + "Example": "```rust,ignore\nlet foo;\n\nif bar() {\n foo = 42;\n} else {\n foo = 0;\n}\n\nlet mut baz = None;\n\nif bar() {\n baz = Some(42);\n}\n```\n\nshould be written\n\n```rust,ignore\nlet foo = if bar() {\n 42\n} else {\n 0\n};\n\nlet baz = if bar() {\n Some(42)\n} else {\n None\n};\n```" + } + }, + { + "id": "useless_transmute", + "group": "nursery", + "level": "Allow", + "docs": { + "What it does": "Checks for transmutes to the original type of the object\nand transmutes that could be a cast.", + "Why is this bad": "Readability. The code tricks people into thinking that\nsomething complex is going on.", + "Known problems": "None.", + "Example": "```rust,ignore\ncore::intrinsics::transmute(t); // where the result type is the same as `t`'s\n```" + } + }, + { + "id": "useless_vec", + "group": "perf", + "level": "Warn", + "docs": { + "What it does": "Checks for usage of `&vec![..]` when using `&[..]` would\nbe possible.", + "Why is this bad": "This is less efficient.", + "Known problems": "None.", + "Example": "```rust\n\n// Bad\nfoo(&vec![1, 2]);\n\n// Good\nfoo(&[1, 2]);\n```" + } + }, + { + "id": "vec_box", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for use of `Vec>` where T: Sized anywhere in the code.", + "Why is this bad": "`Vec` already keeps its contents in a separate area on\nthe heap. So if you `Box` its contents, you just add another level of indirection.", + "Known problems": "Vec> makes sense if T is a large type (see #3530,\n1st comment).", + "Example": "```rust\nstruct X {\n values: Vec>,\n}\n```\n\nBetter:\n\n```rust\nstruct X {\n values: Vec,\n}\n```", + "Configuration": "This lint has the following configuration variables:\n\n* `vec-box-size-threshold: u64`: The size of the boxed type in bytes, where boxing in a `Vec` is allowed (defaults to `4096`)." + } + }, + { + "id": "vec_resize_to_zero", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Finds occurences of `Vec::resize(0, an_int)`", + "Why is this bad": "This is probably an argument inversion mistake.", + "Known problems": "None.", + "Example": "```rust\nvec!(1, 2, 3, 4, 5).resize(0, 5)\n```" + } + }, + { + "id": "verbose_bit_mask", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for bit masks that can be replaced by a call\nto `trailing_zeros`", + "Why is this bad": "`x.trailing_zeros() > 4` is much clearer than `x & 15\n== 0`", + "Known problems": "llvm generates better code for `x & 15 == 0` on x86", + "Example": "```rust\nif x & 0b1111 == 0 { }\n```", + "Configuration": "This lint has the following configuration variables:\n\n* `verbose-bit-mask-threshold: u64`: The maximum allowed size of a bit mask before suggesting to use 'trailing_zeros' (defaults to `1`)." + } + }, + { + "id": "verbose_file_reads", + "group": "restriction", + "level": "Allow", + "docs": { + "What it does": "Checks for use of File::read_to_end and File::read_to_string.", + "Why is this bad": "`fs::{read, read_to_string}` provide the same functionality when `buf` is empty with fewer imports and no intermediate values.\nSee also: [fs::read docs](https://doc.rust-lang.org/std/fs/fn.read.html), [fs::read_to_string docs](https://doc.rust-lang.org/std/fs/fn.read_to_string.html)", + "Known problems": "None.", + "Example": "```rust,no_run\nlet mut f = File::open(\"foo.txt\").unwrap();\nlet mut bytes = Vec::new();\nf.read_to_end(&mut bytes).unwrap();\n```\nCan be written more concisely as\n```rust,no_run\nlet mut bytes = fs::read(\"foo.txt\").unwrap();\n```" + } + }, + { + "id": "vtable_address_comparisons", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for comparisons with an address of a trait vtable.", + "Why is this bad": "Comparing trait objects pointers compares an vtable addresses which\nare not guaranteed to be unique and could vary between different code generation units.\nFurthermore vtables for different types could have the same address after being merged\ntogether.", + "Known problems": "None.", + "Example": "```rust,ignore\nlet a: Rc = ...\nlet b: Rc = ...\nif Rc::ptr_eq(&a, &b) {\n ...\n}\n```" + } + }, + { + "id": "while_immutable_condition", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks whether variables used within while loop condition\ncan be (and are) mutated in the body.", + "Why is this bad": "If the condition is unchanged, entering the body of the loop\nwill lead to an infinite loop.", + "Known problems": "If the `while`-loop is in a closure, the check for mutation of the\ncondition variables in the body can cause false negatives. For example when only `Upvar` `a` is\nin the condition and only `Upvar` `b` gets mutated in the body, the lint will not trigger.", + "Example": "```rust\nlet i = 0;\nwhile i > 10 {\n println!(\"let me loop forever!\");\n}\n```" + } + }, + { + "id": "while_let_loop", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Detects `loop + match` combinations that are easier\nwritten as a `while let` loop.", + "Why is this bad": "The `while let` loop is usually shorter and more\nreadable.", + "Known problems": "Sometimes the wrong binding is displayed (#383).", + "Example": "```rust,no_run\nloop {\n let x = match y {\n Some(x) => x,\n None => break,\n };\n // .. do something with x\n}\n// is easier written as\nwhile let Some(x) = y {\n // .. do something with x\n};\n```" + } + }, + { + "id": "while_let_on_iterator", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for `while let` expressions on iterators.", + "Why is this bad": "Readability. A simple `for` loop is shorter and conveys\nthe intent better.", + "Known problems": "None.", + "Example": "```ignore\nwhile let Some(val) = iter() {\n ..\n}\n```" + } + }, + { + "id": "wildcard_dependencies", + "group": "cargo", + "level": "Allow", + "docs": { + "What it does": "Checks for wildcard dependencies in the `Cargo.toml`.", + "Why is this bad": "[As the edition guide says](https://rust-lang-nursery.github.io/edition-guide/rust-2018/cargo-and-crates-io/crates-io-disallows-wildcard-dependencies.html),\nit is highly unlikely that you work with any possible version of your dependency,\nand wildcard dependencies would cause unnecessary breakage in the ecosystem.", + "Known problems": "None.", + "Example": "```toml\n[dependencies]\nregex = \"*\"\n```" + } + }, + { + "id": "wildcard_enum_match_arm", + "group": "restriction", + "level": "Allow", + "docs": { + "What it does": "Checks for wildcard enum matches using `_`.", + "Why is this bad": "New enum variants added by library updates can be missed.", + "Known problems": "Suggested replacements may be incorrect if guards exhaustively cover some\nvariants, and also may not use correct path to enum if it's not present in the current scope.", + "Example": "```rust\n\n// Bad\nmatch x {\n Foo::A(_) => {},\n _ => {},\n}\n\n// Good\nmatch x {\n Foo::A(_) => {},\n Foo::B(_) => {},\n}\n```" + } + }, + { + "id": "wildcard_imports", + "group": "pedantic", + "level": "Allow", + "docs": { + "What it does": "Checks for wildcard imports `use _::*`.", + "Why is this bad": "wildcard imports can pollute the namespace. This is especially bad if\nyou try to import something through a wildcard, that already has been imported by name from\na different source:\n\n```rust,ignore\nuse crate1::foo; // Imports a function named foo\nuse crate2::*; // Has a function named foo\n\nfoo(); // Calls crate1::foo\n```\n\nThis can lead to confusing error messages at best and to unexpected behavior at worst.", + "Exceptions": "Wildcard imports are allowed from modules named `prelude`. Many crates (including the standard library)\nprovide modules named \"prelude\" specifically designed for wildcard import.\n\n`use super::*` is allowed in test modules. This is defined as any module with \"test\" in the name.\n\nThese exceptions can be disabled using the `warn-on-all-wildcard-imports` configuration flag.", + "Known problems": "If macros are imported through the wildcard, this macro is not included\nby the suggestion and has to be added by hand.\n\nApplying the suggestion when explicit imports of the things imported with a glob import\nexist, may result in `unused_imports` warnings.", + "Example": "```rust,ignore\n// Bad\nuse crate1::*;\n\nfoo();\n```\n\n```rust,ignore\n// Good\nuse crate1::foo;\n\nfoo();\n```", + "Configuration": "This lint has the following configuration variables:\n\n* `warn-on-all-wildcard-imports: bool`: Whether to allow certain wildcard imports (prelude, super in tests). (defaults to `false`)." + } + }, + { + "id": "wildcard_in_or_patterns", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for wildcard pattern used with others patterns in same match arm.", + "Why is this bad": "Wildcard pattern already covers any other pattern as it will match anyway.\nIt makes the code less readable, especially to spot wildcard pattern use in match arm.", + "Known problems": "None.", + "Example": "```rust\n// Bad\nmatch \"foo\" {\n \"a\" => {},\n \"bar\" | _ => {},\n}\n\n// Good\nmatch \"foo\" {\n \"a\" => {},\n _ => {},\n}\n```" + } + }, + { + "id": "write_literal", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "This lint warns about the use of literals as `write!`/`writeln!` args.", + "Why is this bad": "Using literals as `writeln!` args is inefficient\n(c.f., https://github.com/matthiaskrgr/rust-str-bench) and unnecessary\n(i.e., just put the literal in the format string)", + "Known problems": "Will also warn with macro calls as arguments that expand to literals\n-- e.g., `writeln!(buf, \"{}\", env!(\"FOO\"))`.", + "Example": "```rust\n\n// Bad\nwriteln!(buf, \"{}\", \"foo\");\n\n// Good\nwriteln!(buf, \"foo\");\n```" + } + }, + { + "id": "write_with_newline", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "This lint warns when you use `write!()` with a format\nstring that\nends in a newline.", + "Why is this bad": "You should use `writeln!()` instead, which appends the\nnewline.", + "Known problems": "None.", + "Example": "```rust\n\n// Bad\nwrite!(buf, \"Hello {}!\\n\", name);\n\n// Good\nwriteln!(buf, \"Hello {}!\", name);\n```" + } + }, + { + "id": "writeln_empty_string", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "This lint warns when you use `writeln!(buf, \"\")` to\nprint a newline.", + "Why is this bad": "You should use `writeln!(buf)`, which is simpler.", + "Known problems": "None.", + "Example": "```rust\n\n// Bad\nwriteln!(buf, \"\");\n\n// Good\nwriteln!(buf);\n```" + } + }, + { + "id": "wrong_pub_self_convention", + "group": "restriction", + "level": "Allow", + "docs": { + "What it does": "This is the same as\n[`wrong_self_convention`](#wrong_self_convention), but for public items.", + "Why is this bad": "See [`wrong_self_convention`](#wrong_self_convention).", + "Known problems": "Actually *renaming* the function may break clients if\nthe function is part of the public interface. In that case, be mindful of\nthe stability guarantees you've given your users.", + "Example": "```rust\nimpl<'a> X {\n pub fn as_str(self) -> &'a str {\n \"foo\"\n }\n}\n```" + } + }, + { + "id": "wrong_self_convention", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Checks for methods with certain name prefixes and which\ndoesn't match how self is taken. The actual rules are:\n\n|Prefix |`self` taken |\n|-------|----------------------|\n|`as_` |`&self` or `&mut self`|\n|`from_`| none |\n|`into_`|`self` |\n|`is_` |`&self` or none |\n|`to_` |`&self` |", + "Why is this bad": "Consistency breeds readability. If you follow the\nconventions, your users won't be surprised that they, e.g., need to supply a\nmutable reference to a `as_..` function.", + "Known problems": "None.", + "Example": "```rust\nimpl X {\n fn as_str(self) -> &'static str {\n // ..\n }\n}\n```" + } + }, + { + "id": "wrong_transmute", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for transmutes that can't ever be correct on any\narchitecture.", + "Why is this bad": "It's basically guaranteed to be undefined behaviour.", + "Known problems": "When accessing C, users might want to store pointer\nsized objects in `extradata` arguments to save an allocation.", + "Example": "```ignore\nlet ptr: *const T = core::intrinsics::transmute('x')\n```" + } + }, + { + "id": "zero_divided_by_zero", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Checks for `0.0 / 0.0`.", + "Why is this bad": "It's less readable than `f32::NAN` or `f64::NAN`.", + "Known problems": "None.", + "Example": "```rust\n// Bad\nlet nan = 0.0f32 / 0.0;\n\n// Good\nlet nan = f32::NAN;\n```" + } + }, + { + "id": "zero_prefixed_literal", + "group": "complexity", + "level": "Warn", + "docs": { + "What it does": "Warns if an integral constant literal starts with `0`.", + "Why is this bad": "In some languages (including the infamous C language\nand most of its\nfamily), this marks an octal constant. In Rust however, this is a decimal\nconstant. This could\nbe confusing for both the writer and a reader of the constant.", + "Known problems": "None.", + "Example": "In Rust:\n```rust\nfn main() {\n let a = 0123;\n println!(\"{}\", a);\n}\n```\n\nprints `123`, while in C:\n\n```c\n#include \n\nint main() {\n int a = 0123;\n printf(\"%d\\n\", a);\n}\n```\n\nprints `83` (as `83 == 0o123` while `123 == 0o173`)." + } + }, + { + "id": "zero_ptr", + "group": "style", + "level": "Warn", + "docs": { + "What it does": "Catch casts from `0` to some pointer type", + "Why is this bad": "This generally means `null` and is better expressed as\n{`std`, `core`}`::ptr::`{`null`, `null_mut`}.", + "Known problems": "None.", + "Example": "```rust\n// Bad\nlet a = 0 as *const u32;\n\n// Good\nlet a = std::ptr::null::();\n```" + } + }, + { + "id": "zero_width_space", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for the Unicode zero-width space in the code.", + "Why is this bad": "Having an invisible character in the code makes for all\nsorts of April fools, but otherwise is very much frowned upon.", + "Known problems": "None.", + "Example": "You don't see it, but there may be a zero-width space\nsomewhere in this text." + } + }, + { + "id": "zst_offset", + "group": "correctness", + "level": "Deny", + "docs": { + "What it does": "Checks for `offset(_)`, `wrapping_`{`add`, `sub`}, etc. on raw pointers to\nzero-sized types", + "Why is this bad": "This is a no-op, and likely unintended", + "Known problems": "None", + "Example": "```rust\nunsafe { (&() as *const ()).offset(1) };\n```" + } + } +] \ No newline at end of file diff --git a/stable b/stable index a1700575d..5d00be4ab 120000 --- a/stable +++ b/stable @@ -1 +1 @@ -rust-1.45.2 \ No newline at end of file +rust-1.46.0 \ No newline at end of file diff --git a/versions.json b/versions.json index 016313844..b954c6867 100644 --- a/versions.json +++ b/versions.json @@ -125,6 +125,7 @@ "rust-1.45.0", "rust-1.45.1", "rust-1.45.2", + "rust-1.46.0", "beta", "stable", "master"