No description
Find a file
2015-11-22 21:52:06 +05:30
src Add block_in_if lint, #434 2015-11-22 21:52:06 +05:30
tests Add block_in_if lint, #434 2015-11-22 21:52:06 +05:30
util lib: add clippy_pedantic group with all Allow by default lints (fixes #265) 2015-09-01 18:05:28 +02:00
.gitignore Add eta reduction (fixes #29) 2015-05-10 11:49:08 +05:30
.travis.yml Address review comments, move to travis 2015-08-13 21:45:50 +05:30
Cargo.toml Crates bump 2015-11-20 16:21:14 +05:30
CONTRIBUTING.md add a few words on dogfood + update_lints 2015-08-14 11:30:39 +02:00
README.md Add block_in_if lint, #434 2015-11-22 21:52:06 +05:30

#rust-clippy Build Status

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

Jump to usage instructions

##Lints There are 76 lints included in this crate:

name default meaning
approx_constant warn the approximate of a known float constant (in std::f64::consts or std::f32::consts) is found; suggests to use the constant
bad_bit_mask warn expressions of the form _ & mask == select that will only ever return true or false (because in the example select containing bits that mask doesn't have)
block_in_if_condition_expr warn braces can be eliminated in conditions that are expressions, e.g if { true } ...
block_in_if_condition_stmt warn avoid complex blocks in conditions, instead move the block higher and bind it with 'let'; e.g: if { let x = true; x } ...
box_vec warn usage of Box<Vec<T>>, vector elements are already on the heap
cast_possible_truncation allow casts that may cause truncation of the value, e.g x as u8 where x: u32, or x as i32 where x: f32
cast_possible_wrap allow casts that may cause wrapping around the value, e.g x as i32 where x: u32 and x > i32::MAX
cast_precision_loss allow casts that cause loss of precision, e.g x as f32 where x: u64
cast_sign_loss allow casts from signed types to unsigned types, e.g x as u32 where x: i32
cmp_nan deny comparisons to NAN (which will always return false, which is probably not intended)
cmp_owned warn creating owned instances for comparing with others, e.g. x == "foo".to_string()
collapsible_if warn two nested if-expressions can be collapsed into one, e.g. if x { if y { foo() } } can be written as if x && y { foo() }
empty_loop warn empty loop {} detected
eq_op warn equal operands on both sides of a comparison or bitwise combination (e.g. x == x)
explicit_counter_loop warn for-looping with an explicit counter when _.enumerate() would do
explicit_iter_loop warn for-looping over _.iter() or _.iter_mut() when &_ or &mut _ would do
float_cmp warn using == or != on float values (as floating-point operations usually involve rounding errors, it is always better to check for approximate equality within small bounds)
identity_op warn using identity operations, e.g. x + 0 or y / 1
ineffective_bit_mask warn expressions where a bit mask will be rendered useless by a comparison, e.g. `(x
inline_always warn #[inline(always)] is a bad idea in most cases
iter_next_loop warn for-looping over _.next() which is probably not intended
len_without_is_empty warn traits and impls that have .len() but not .is_empty()
len_zero warn checking .len() == 0 or .len() > 0 (or similar) when .is_empty() could be used instead
let_and_return warn creating a let-binding and then immediately returning it like let x = expr; x at the end of a block
let_unit_value warn creating a let binding to a value of unit type, which usually can't be used afterwards
linkedlist warn usage of LinkedList, usually a vector is faster, or a more specialized data structure like a VecDeque
map_clone warn using `.map(
match_bool warn a match on boolean expression; recommends if..else block instead
match_ref_pats warn a match has all arms prefixed with &; the match expression can be dereferenced instead
min_max warn min(_, max(_, _)) (or vice versa) with bounds clamping the result to a constant
modulo_one warn taking a number modulo 1, which always returns 0
mut_mut allow usage of double-mut refs, e.g. &mut &mut ... (either copy'n'paste error, or shows a fundamental misunderstanding of references)
mutex_atomic warn using a Mutex where an atomic value could be used instead
mutex_integer allow using a Mutex for an integer type
needless_bool warn if-statements with plain booleans in the then- and else-clause, e.g. if p { true } else { false }
needless_lifetimes warn using explicit lifetimes for references in function arguments when elision rules would allow omitting them
needless_range_loop warn for-looping over a range of indices where an iterator over items would do
needless_return warn using a return statement like return expr; where an expression would suffice
needless_update warn using { ..base } when there are no missing fields
no_effect warn statements with no effect
non_ascii_literal allow using any literal non-ASCII chars in a string literal; suggests using the \u escape instead
nonsensical_open_options warn nonsensical combination of options for opening a file
option_unwrap_used allow using Option.unwrap(), which should at least get a better message using expect()
precedence warn catches operations where precedence may be unclear. See the wiki for a list of cases caught
ptr_arg warn fn arguments of the type &Vec<...> or &String, suggesting to use &[...] or &str instead, respectively
range_step_by_zero warn using Range::step_by(0), which produces an infinite iterator
range_zip_with_len warn zipping iterator with a range when enumerate() would do
redundant_closure warn using redundant closures, i.e. `
redundant_pattern warn using name @ _ in a pattern
result_unwrap_used allow using Result.unwrap(), which might be better handled
reverse_range_loop warn Iterating over an empty range, such as 10..0 or 5..5
shadow_reuse allow rebinding a name to an expression that re-uses the original value, e.g. let x = x + 1
shadow_same allow rebinding a name to itself, e.g. let mut x = &mut x
shadow_unrelated allow The name is re-bound without even using the original value
should_implement_trait warn defining a method that should be implementing a std trait
single_match warn a match statement with a single nontrivial arm (i.e, where the other arm is _ => {}) is used; recommends if let instead
str_to_string warn using to_string() on a str, which should be to_owned()
string_add allow using x + .. where x is a String; suggests using push_str() instead
string_add_assign allow using x = x + .. where x is a String; suggests using push_str() instead
string_to_string warn calling String.to_string() which is a no-op
temporary_assignment warn assignments to temporaries
toplevel_ref_arg warn An entire binding was declared as ref, in a function argument (fn foo(ref x: Bar)), or a let statement (let ref x = foo()). In such cases, it is preferred to take references with &.
type_complexity warn usage of very complex types; recommends factoring out parts into type definitions
unicode_not_nfc allow using a unicode literal not in NFC normal form (see http://www.unicode.org/reports/tr15/ for further information)
unit_cmp warn comparing unit values (which is always true or false, respectively)
unnecessary_mut_passed warn an argument is passed as a mutable reference although the function/method only demands an immutable reference
unstable_as_mut_slice warn as_mut_slice is not stable and can be replaced by &mut v[..]see https://github.com/rust-lang/rust/issues/27729
unstable_as_slice warn as_slice is not stable and can be replaced by & v[..]see https://github.com/rust-lang/rust/issues/27729
unused_collect warn collect()ing an iterator without using the result; this is usually better written as a for loop
useless_transmute warn transmutes that have the same to and from types
while_let_loop warn loop { if let { ... } else break } can be written as a while let loop
while_let_on_iterator warn using a while-let loop instead of a for loop on an iterator
wrong_pub_self_convention allow defining a public method named with an established prefix (like "into_") that takes self with the wrong convention
wrong_self_convention warn defining a method named with an established prefix (like "into_") that takes self with the wrong convention
zero_divided_by_zero warn usage of 0.0 / 0.0 to obtain NaN instead of std::f32::NaN or std::f64::NaN
zero_width_space deny using a zero-width space in a string literal, which is confusing

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

##Usage

Compiler plugins are highly unstable and will only work with a nightly Rust for now. 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 may also use cargo clippy, a custom cargo subcommand that runs clippy on a given project.

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) }

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

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!

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))]

##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.