Fix dogfood problem
2 files changed
tree: 0fdf45a3ccf726fa9e6cf1e45f4f499cbc817f7e
  1. .github/
  2. clippy_lints/
  3. mini-macro/
  4. src/
  5. tests/
  6. util/
  7. .editorconfig
  8. .gitignore
  9. .remarkrc.json
  10. .travis.yml
  11. Cargo.toml
  12. CHANGELOG.md
  13. CONTRIBUTING.md
  14. README.md
  15. rustfmt.toml
README.md

rust-clippy

Build Status Clippy Linting Result Current Version License: MPL-2.0

A collection of lints to catch common mistakes and improve your Rust code.

Table of contents:

Usage

As a general rule clippy will only work with the latest Rust nightly for now.

As a Compiler Plugin

Since stable Rust is backwards compatible, you should be able to compile your stable programs with nightly Rust with clippy plugged in to circumvent this.

Add in your Cargo.toml:

[dependencies]
clippy = "*"

You then need to add #![feature(plugin)] and #![plugin(clippy)] to the top of your crate entry point (main.rs or lib.rs).

Sample main.rs:

#![feature(plugin)]

#![plugin(clippy)]


fn main(){
    let x = Some(1u8);
    match x {
        Some(y) => println!("{:?}", y),
        _ => ()
    }
}

Produces this warning:

src/main.rs:8:5: 11:6 warning: you seem to be trying to use match for destructuring a single type. Consider using `if let`, #[warn(single_match)] on by default
src/main.rs:8     match x {
src/main.rs:9         Some(y) => println!("{:?}", y),
src/main.rs:10         _ => ()
src/main.rs:11     }
src/main.rs:8:5: 11:6 help: Try
if let Some(y) = x { println!("{:?}", y) }

As a cargo subcommand (cargo clippy)

An alternate way to use clippy is by installing clippy through cargo as a cargo subcommand.

cargo install clippy

Now you can run clippy by invoking cargo clippy, or rustup run nightly cargo clippy directly from a directory that is usually compiled with stable.

In case you are not using rustup, you need to set the environment flag SYSROOT during installation so clippy knows where to find librustc and similar crates.

SYSROOT=/path/to/rustc/sysroot cargo install clippy

Running clippy from the command line without installing

To have cargo compile your crate with clippy without needing #![plugin(clippy)] in your code, you can use:

cargo rustc -- -L /path/to/clippy_so -Z extra-plugins=clippy

Note: Be sure that clippy was compiled with the same version of rustc that cargo invokes here!

Optional dependency

If you want to make clippy an optional dependency, you can do the following:

In your Cargo.toml:

[dependencies]
clippy = {version = "*", optional = true}

[features]
default = []

And, in your main.rs or lib.rs:

#![cfg_attr(feature="clippy", feature(plugin))]

#![cfg_attr(feature="clippy", plugin(clippy))]

Then build by enabling the feature: cargo build --features "clippy"

Instead of adding the cfg_attr attributes you can also run clippy on demand: cargo rustc --features clippy -- -Z no-trans -Z extra-plugins=clippy (the -Z no trans, while not neccessary, will stop the compilation process after typechecking (and lints) have completed, which can significantly reduce the runtime).

Configuration

Some lints can be configured in a clippy.toml file. It contains basic variable = value mapping eg.

blacklisted-names = ["toto", "tata", "titi"]
cyclomatic-complexity-threshold = 30

See the wiki for more information about which lints can be configured and the meaning of the variables.

You can also specify the path to the configuration file with:

#![plugin(clippy(conf_file="path/to/clippy's/configuration"))]

To deactivate the “for further information visit wiki-link” message you can define the CLIPPY_DISABLE_WIKI_LINKS environment variable.

Allowing/denying lints

You can add options to allow/warn/deny:

  • the whole set of Warn lints using the clippy lint group (#![deny(clippy)])

  • all lints using both the clippy and clippy_pedantic lint groups (#![deny(clippy)], #![deny(clippy_pedantic)]). Note that clippy_pedantic contains some very aggressive lints prone to false positives.

  • only some lints (#![deny(single_match, box_vec)], etc)

  • allow/warn/deny can be limited to a single function or module using #[allow(...)], etc

Note: deny produces errors instead of warnings.

Link with clippy service

clippy-service is a rust web initiative providing rust-clippy as a web service.

Both projects are independent and maintained by different people (even if some clippy-service's contributions are authored by some rust-clippy members).

You can check out this great service at clippy.bashy.io.

Lints

There are 173 lints included in this crate:

namedefaulttriggers on
absurd_extreme_comparisonswarna comparison with a maximum or minimum value that is always true or false
almost_swappedwarnfoo = bar; bar = foo sequence
approx_constantwarnthe approximate of a known float constant (in std::fXX::consts)
assign_op_patternwarnassigning the result of an operation on a variable to that same variable
assign_opsallowany compound assignment operation
bad_bit_maskwarnexpressions of the form _ & mask == select that will only ever return true or false
blacklisted_namewarnusage of a blacklisted/placeholder name
block_in_if_condition_exprwarnbraces that can be eliminated in conditions, e.g if { true } ...
block_in_if_condition_stmtwarncomplex blocks in conditions, e.g. if { let x = true; x } ...
bool_comparisonwarncomparing a variable to a boolean, e.g. if x == true
box_vecwarnusage of Box<Vec<T>>, vector elements are already on the heap
boxed_localwarnusing Box<T> where unnecessary
builtin_type_shadowwarnshadowing a builtin type
cast_possible_truncationallowcasts that may cause truncation of the value, e.g x as u8 where x: u32, or x as i32 where x: f32
cast_possible_wrapallowcasts that may cause wrapping around the value, e.g x as i32 where x: u32 and x > i32::MAX
cast_precision_lossallowcasts that cause loss of precision, e.g x as f32 where x: u64
cast_sign_lossallowcasts from signed types to unsigned types, e.g x as u32 where x: i32
char_lit_as_u8warncasting a character literal to u8
chars_next_cmpwarnusing .chars().next() to check if a string starts with a char
clone_double_refwarnusing clone on &&T
clone_on_copywarnusing clone on a Copy type
cmp_nandenycomparisons to NAN, which will always return false, probably not intended
cmp_nullwarncomparing a pointer to a null pointer, suggesting to use .is_null() instead.
cmp_ownedwarncreating owned instances for comparing with others, e.g. x == "foo".to_string()
collapsible_ifwarnifs that can be collapsed (e.g. if x { if y { ... } } and else { if x { ... } })
crosspointer_transmutewarntransmutes that have to or from types that are a pointer to the other
cyclomatic_complexitywarnfunctions that should be split up into multiple functions
deprecated_semverwarnuse of #[deprecated(since = "x")] where x is not semver
derive_hash_xor_eqwarnderiving Hash but implementing PartialEq explicitly
diverging_sub_expressionwarnwhether an expression contains a diverging sub expression
doc_markdownwarnpresence of _, :: or camel-case outside backticks in documentation
double_negwarn--x, which is a double negation of x and not a pre-decrement as in C/C++
drop_refwarncalls to std::mem::drop with a reference instead of an owned value
duplicate_underscore_argumentwarnfunction arguments having names which only differ by an underscore
empty_loopwarnempty loop {}, which should block or sleep
enum_clike_unportable_variantwarnC-like enums that are repr(isize/usize) and have values that don't fit into an i32
enum_glob_useallowuse items that import all variants of an enum
enum_variant_nameswarnenums where all variants share a prefix/postfix
eq_opwarnequal operands on both sides of a comparison or bitwise combination (e.g. x == x)
eval_order_dependencewarnwhether a variable read occurs before a write depends on sub-expression evaluation order
expl_impl_clone_on_copywarnimplementing Clone explicitly on Copy types
explicit_counter_loopwarnfor-looping with an explicit counter when _.enumerate() would do
explicit_into_iter_loopwarnfor-looping over _.into_iter() when _ would do
explicit_iter_loopwarnfor-looping over _.iter() or _.iter_mut() when &_ or &mut _ would do
extend_from_slicewarn.extend_from_slice(_) is a faster way to extend a Vec by a slice
filter_mapallowusing combinations of filter, map, filter_map and flat_map which can usually be written as a single method call
filter_nextwarnusing filter(p).next(), which is more succinctly expressed as .find(p)
float_arithmeticallowany floating-point arithmetic statement
float_cmpwarnusing == or != on float values instead of comparing difference with an epsilon
for_kv_mapwarnlooping on a map using iter when keys or values would do
for_loop_over_optionwarnfor-looping over an Option, which is more clearly expressed as an if let
for_loop_over_resultwarnfor-looping over a Result, which is more clearly expressed as an if let
identity_opwarnusing identity operations, e.g. x + 0 or y / 1
if_let_some_resultwarnusage of ok() in if let Some(pat) statements is unnecessary, match on Ok(pat) instead
if_not_elseallowif branches that could be swapped so no negation operation is necessary on the condition
if_same_then_elsewarnif with the same then and else blocks
ifs_same_condwarnconsecutive ifs with the same condition
indexing_slicingallowindexing/slicing usage
ineffective_bit_maskwarnexpressions where a bit mask will be rendered useless by a comparison, e.g. `(x
inline_alwayswarnuse of #[inline(always)]
integer_arithmeticallowany integer arithmetic statement
invalid_regexdenyinvalid regular expressions
invalid_upcast_comparisonsallowa comparison involving an upcast which is always true or false
items_after_statementsallowblocks where an item comes after a statement
iter_next_loopwarnfor-looping over _.next() which is probably not intended
iter_nthwarnusing .iter().nth() on a standard library type with O(1) element access
len_without_is_emptywarntraits or impls with a public len method but no corresponding is_empty method
len_zerowarnchecking .len() == 0 or .len() > 0 (or similar) when .is_empty() could be used instead
let_and_returnwarncreating a let-binding and then immediately returning it like let x = expr; x at the end of a block
let_unit_valuewarncreating a let binding to a value of unit type, which usually can't be used afterwards
linkedlistwarnusage of LinkedList, usually a vector is faster, or a more specialized data structure like a VecDeque
logic_bugwarnboolean expressions that contain terminals which can be eliminated
manual_swapwarnmanual swap of two variables
many_single_char_nameswarntoo many single character bindings
map_clonewarnusing `.map(
map_entrywarnuse of contains_key followed by insert on a HashMap or BTreeMap
match_boolwarna match on a boolean expression instead of an if..else block
match_overlapping_armwarna match with overlapping arms
match_ref_patswarna match or if let with all arms prefixed with & instead of deref-ing the match expression
match_same_armswarnmatch with identical arm bodies
mem_forgetallowmem::forget usage on Drop types, likely to cause memory leaks
min_maxwarnmin(_, max(_, _)) (or vice versa) with bounds clamping the result to a constant
misrefactored_assign_opwarnhaving a variable on both sides of an assign op
missing_docs_in_private_itemsallowdetects missing documentation for public and private members
mixed_case_hex_literalswarnhex literals whose letter digits are not consistently upper- or lowercased
module_inceptionwarnmodules that have the same name as their parent module
modulo_onewarntaking a number modulo 1, which always returns 0
mut_mutallowusage of double-mut refs, e.g. &mut &mut ...
mutex_atomicwarnusing a mutex where an atomic value could be used instead
mutex_integerallowusing a mutex for an integer type
needless_boolwarnif-statements with plain booleans in the then- and else-clause, e.g. if p { true } else { false }
needless_borrowwarntaking a reference that is going to be automatically dereferenced
needless_lifetimeswarnusing explicit lifetimes for references in function arguments when elision rules would allow omitting them
needless_range_loopwarnfor-looping over a range of indices where an iterator over items would do
needless_returnwarnusing a return statement like return expr; where an expression would suffice
needless_updatewarnusing Foo { ..base } when there are no missing fields
neg_multiplywarnmultiplying integers with -1
new_ret_no_selfwarnnot returning Self in a new method
new_without_defaultwarnfn new() -> Self method without Default implementation
new_without_default_derivewarnfn new() -> Self without #[derive]able Default implementation
no_effectwarnstatements with no effect
non_ascii_literalallowusing any literal non-ASCII chars in a string literal instead of using the \\u escape
nonminimal_boolallowboolean expressions that can be written more concisely
nonsensical_open_optionswarnnonsensical combination of options for opening a file
not_unsafe_ptr_arg_derefwarnpublic functions dereferencing raw pointer arguments but not marked unsafe
ok_expectwarnusing ok().expect(), which gives worse error messages than calling expect directly on the Result
option_map_unwrap_orallowusing Option.map(f).unwrap_or(a), which is more succinctly expressed as map_or(a, f)
option_map_unwrap_or_elseallowusing Option.map(f).unwrap_or_else(g), which is more succinctly expressed as map_or_else(g, f)
option_unwrap_usedallowusing Option.unwrap(), which should at least get a better message using expect()
or_fun_callwarnusing any *or method with a function call, which suggests *or_else
out_of_bounds_indexingdenyout of bounds constant indexing
overflow_check_conditionalwarnoverflow checks inspired by C which are likely to panic
panic_paramswarnmissing parameters in panic! calls
precedencewarnoperations where precedence may be unclear
print_stdoutallowprinting on stdout
print_with_newlinewarnusing print!() with a format string that ends in a newline
ptr_argwarnfn arguments of the type &Vec<...> or &String, suggesting to use &[...] or &str instead, respectively
range_step_by_zerowarnusing Range::step_by(0), which produces an infinite iterator
range_zip_with_lenwarnzipping iterator with a range when enumerate() would do
redundant_closurewarnredundant closures, i.e. `
redundant_closure_callwarnthrowaway closures called in the expression they are defined
redundant_patternwarnusing name @ _ in a pattern
regex_macrowarnuse of regex!(_) instead of Regex::new(_)
result_unwrap_usedallowusing Result.unwrap(), which might be better handled
reverse_range_loopwarniteration over an empty range, such as 10..0 or 5..5
search_is_somewarnusing an iterator search followed by is_some(), which is more succinctly expressed as a call to any()
serde_api_misusewarnvarious things that will negatively affect your serde experience
shadow_reuseallowrebinding a name to an expression that re-uses the original value, e.g. let x = x + 1
shadow_sameallowrebinding a name to itself, e.g. let mut x = &mut x
shadow_unrelatedallowrebinding a name without even using the original value
should_implement_traitwarndefining a method that should be implementing a std trait
similar_namesallowsimilarly named items and bindings
single_char_patternwarnusing a single-character str where a char could be used, e.g. _.split("x")
single_matchwarna match statement with a single nontrivial arm (i.e, where the other arm is _ => {}) instead of if let
single_match_elseallowa match statement with a two arms where the second arm's pattern is a wildcard instead of if let
string_addallowusing x + .. where x is a String instead of push_str()
string_add_assignallowusing x = x + .. where x is a String instead of push_str()
string_lit_as_byteswarncalling as_bytes on a string literal instead of using a byte string literal
stutterallowtype names prefixed/postfixed with their containing module's name
suspicious_assignment_formattingwarnsuspicious formatting of *=, -= or !=
suspicious_else_formattingwarnsuspicious formatting of else if
temporary_assignmentwarnassignments to temporaries
temporary_cstring_as_ptrwarngetting the inner pointer of a temporary CString
too_many_argumentswarnfunctions with too many arguments
toplevel_ref_argwarnan entire binding declared as ref, in a function argument or a let statement
transmute_ptr_to_refwarntransmutes from a pointer to a reference type
trivial_regexwarntrivial regular expressions
type_complexitywarnusage of very complex types that might be better factored into type definitions
unicode_not_nfcallowusing a unicode literal not in NFC normal form (see unicode tr15 for further information)
unit_cmpwarncomparing unit values
unnecessary_mut_passedwarnan argument passed as a mutable reference although the callee only demands an immutable reference
unnecessary_operationwarnouter expressions with no effect
unneeded_field_patternwarnstruct fields bound to a wildcard instead of using ..
unsafe_removed_from_namewarnunsafe removed from API names on import
unseparated_literal_suffixallowliterals whose suffix is not separated by an underscore
unused_collectwarncollect()ing an iterator without using the result; this is usually better written as a for loop
unused_labelwarnunused labels
unused_lifetimeswarnunused lifetimes in function definitions
use_debugallowuse of Debug-based formatting
used_underscore_bindingallowusing a binding which is prefixed with an underscore
useless_attributewarnuse of lint attributes on extern crate items
useless_formatwarnuseless use of format!
useless_let_if_seqwarnunidiomatic let mut declaration followed by initialization in if
useless_transmutewarntransmutes that have the same to and from types or could be a cast/coercion
useless_vecwarnuseless vec!
while_let_loopwarnloop { if let { ... } else break }, which can be written as a while let loop
while_let_on_iteratorwarnusing a while-let loop instead of a for loop on an iterator
wrong_pub_self_conventionallowdefining a public method named with an established prefix (like “into_”) that takes self with the wrong convention
wrong_self_conventionwarndefining a method named with an established prefix (like “into_”) that takes self with the wrong convention
wrong_transmutewarntransmutes that are confusing at best, undefined behaviour at worst and always useless
zero_divided_by_zerowarnusage of 0.0 / 0.0 to obtain NaN instead of std::f32::NaN or std::f64::NaN
zero_prefixed_literalwarninteger literals starting with 0
zero_width_spacedenyusing a zero-width space in a string literal, which is confusing

More to come, please file an issue if you have ideas!

License

Licensed under MPL. If you‘re having issues with the license, let me know and I’ll try to change it to something more permissive.