Merge pull request #623 from mcarton/redundant

Be more consistent in lint declarations
This commit is contained in:
Manish Goregaokar 2016-02-06 12:14:03 +05:30
commit f53a830c8c
46 changed files with 472 additions and 275 deletions

View file

@ -6,7 +6,7 @@ use syntax::ast::Lit_::*;
use syntax::ast::Lit;
use syntax::ast::FloatTy::*;
/// **What it does:** This lint checks for floating point literals that approximate constants which are defined in [`std::f32::consts`](https://doc.rust-lang.org/stable/std/f32/consts/#constants) or [`std::f64::consts`](https://doc.rust-lang.org/stable/std/f64/consts/#constants), respectively, suggesting to use the predefined constant. This lint is `Warn` by default.
/// **What it does:** This lint checks for floating point literals that approximate constants which are defined in [`std::f32::consts`](https://doc.rust-lang.org/stable/std/f32/consts/#constants) or [`std::f64::consts`](https://doc.rust-lang.org/stable/std/f64/consts/#constants), respectively, suggesting to use the predefined constant.
///
/// **Why is this bad?** Usually, the definition in the standard library is more precise than what people come up with. If you find that your definition is actually more precise, please [file a Rust issue](https://github.com/rust-lang/rust/issues).
///

View file

@ -9,7 +9,7 @@ use syntax::attr::*;
use syntax::ast::{Attribute, Lit, Lit_, MetaList, MetaWord, MetaNameValue};
use utils::{in_macro, match_path, span_lint, BEGIN_UNWIND};
/// **What it does:** This lint `Warn`s on items annotated with `#[inline(always)]`, unless the annotated function is empty or simply panics.
/// **What it does:** This lint checks for items annotated with `#[inline(always)]`, unless the annotated function is empty or simply panics.
///
/// **Why is this bad?** While there are valid uses of this annotation (and once you know when to use it, by all means `allow` this lint), it's a common newbie-mistake to pepper one's code with it.
///
@ -22,10 +22,12 @@ use utils::{in_macro, match_path, span_lint, BEGIN_UNWIND};
/// #[inline(always)]
/// fn not_quite_hot_code(..) { ... }
/// ```
declare_lint! { pub INLINE_ALWAYS, Warn,
"`#[inline(always)]` is a bad idea in most cases" }
declare_lint! {
pub INLINE_ALWAYS, Warn,
"`#[inline(always)]` is a bad idea in most cases"
}
/// **What it does:** This lint `Warn`s on `#[deprecated]` annotations with a `since` field that is not a valid semantic version..
/// **What it does:** This lint checks for `#[deprecated]` annotations with a `since` field that is not a valid semantic version..
///
/// **Why is this bad?** For checking the version of the deprecation, it must be valid semver. Failing that, the contained information is useless.
///
@ -36,8 +38,10 @@ declare_lint! { pub INLINE_ALWAYS, Warn,
/// #[deprecated(since = "forever")]
/// fn something_else(..) { ... }
/// ```
declare_lint! { pub DEPRECATED_SEMVER, Warn,
"`Warn` on `#[deprecated(since = \"x\")]` where x is not semver" }
declare_lint! {
pub DEPRECATED_SEMVER, Warn,
"`Warn` on `#[deprecated(since = \"x\")]` where x is not semver"
}
#[derive(Copy,Clone)]
pub struct AttrPass;

View file

@ -8,7 +8,7 @@ use syntax::ast::Lit_::*;
use utils::span_lint;
/// **What it does:** This lint checks for incompatible bit masks in comparisons. It is `Warn` by default.
/// **What it does:** This lint checks for incompatible bit masks in comparisons.
///
/// The formula for detecting if an expression of the type `_ <bit_op> m <cmp_op> c` (where `<bit_op>`
/// is one of {`&`, `|`} and `<cmp_op>` is one of {`!=`, `>=`, `>`, `!=`, `>=`, `>`}) can be determined from the following table:
@ -43,8 +43,6 @@ declare_lint! {
/// |`>` / `<=`|`|` / `^`|`x | 2 > 3`|`x > 3`|
/// |`<` / `>=`|`|` / `^`|`x ^ 1 < 4`|`x < 4`|
///
/// This lint is `Warn` by default.
///
/// **Why is this bad?** Not equally evil as [`bad_bit_mask`](#bad_bit_mask), but still a bit misleading, because the bit mask is ineffective.
///
/// **Known problems:** False negatives: This lint will only match instances where we have figured out the math (which is for a power-of-two compared value). This means things like `x | 1 >= 7` (which would be better written as `x >= 6`) will not be reported (but bit masks like this are fairly uncommon).

View file

@ -3,7 +3,7 @@ use rustc::lint::{LateLintPass, LateContext, LintArray, LintPass};
use rustc_front::intravisit::{Visitor, walk_expr};
use utils::*;
/// **What it does:** This lint checks for `if` conditions that use blocks to contain an expression. It is `Warn` by default.
/// **What it does:** This lint checks for `if` conditions that use blocks to contain an expression.
///
/// **Why is this bad?** It isn't really rust style, same as using parentheses to contain expressions.
///
@ -15,7 +15,7 @@ declare_lint! {
"braces can be eliminated in conditions that are expressions, e.g `if { true } ...`"
}
/// **What it does:** This lint checks for `if` conditions that use blocks containing statements, or conditions that use closures with blocks. It is `Warn` by default.
/// **What it does:** This lint checks for `if` conditions that use blocks containing statements, or conditions that use closures with blocks.
///
/// **Why is this bad?** Using blocks in the condition makes it hard to read.
///

View file

@ -20,7 +20,7 @@ use utils::{in_macro, snippet, snippet_block, span_lint_and_then};
/// **What it does:** This lint checks for nested `if`-statements which can be collapsed by
/// `&&`-combining their conditions and for `else { if .. }` expressions that can be collapsed to
/// `else if ..`. It is `Warn` by default.
/// `else if ..`.
///
/// **Why is this bad?** Each `if`-statement adds one level of nesting, which makes code look more complex than it really is.
///

View file

@ -11,15 +11,17 @@ use rustc_front::intravisit::{Visitor, walk_expr};
use utils::{in_macro, LimitStack, span_help_and_lint};
/// **What it does:** It `Warn`s on methods with high cyclomatic complexity
/// **What it does:** This lint checks for methods with high cyclomatic complexity
///
/// **Why is this bad?** Methods of high cyclomatic complexity tend to be badly readable. Also LLVM will usually optimize small methods better.
///
/// **Known problems:** Sometimes it's hard to find a way to reduce the complexity
///
/// **Example:** No. You'll see it when you get the warning.
declare_lint! { pub CYCLOMATIC_COMPLEXITY, Warn,
"finds functions that should be split up into multiple functions" }
declare_lint! {
pub CYCLOMATIC_COMPLEXITY, Warn,
"finds functions that should be split up into multiple functions"
}
pub struct CyclomaticComplexity {
limit: LimitStack,

View file

@ -15,12 +15,14 @@ use utils::{match_def_path, span_note_and_lint};
/// **Example:**
/// ```rust
/// let mut lock_guard = mutex.lock();
/// std::mem::drop(&lock_guard) //Should have been drop(lock_guard), mutex still locked
/// std::mem::drop(&lock_guard) // Should have been drop(lock_guard), mutex still locked
/// operation_that_requires_mutex_to_be_unlocked();
/// ```
declare_lint!(pub DROP_REF, Warn,
declare_lint! {
pub DROP_REF, Warn,
"call to `std::mem::drop` with a reference instead of an owned value, \
which will not call the `Drop::drop` method on the underlying value");
which will not call the `Drop::drop` method on the underlying value"
}
#[allow(missing_copy_implementations)]
pub struct DropRefPass;

View file

@ -14,8 +14,10 @@ use utils::span_help_and_lint;
/// **Known problems:** None
///
/// **Example:** enum Cake { BlackForestCake, HummingbirdCake }
declare_lint! { pub ENUM_VARIANT_NAMES, Warn,
"finds enums where all variants share a prefix/postfix" }
declare_lint! {
pub ENUM_VARIANT_NAMES, Warn,
"finds enums where all variants share a prefix/postfix"
}
pub struct EnumVariantNames;

View file

@ -4,7 +4,7 @@ use rustc_front::util as ast_util;
use utils::{is_exp_equal, span_lint};
/// **What it does:** This lint checks for equal operands to comparisons and bitwise binary operators (`&`, `|` and `^`). It is `Warn` by default.
/// **What it does:** This lint checks for equal operands to comparisons and bitwise binary operators (`&`, `|` and `^`).
///
/// **Why is this bad?** This is usually just a typo.
///

View file

@ -14,7 +14,7 @@ use utils::span_lint;
pub struct EscapePass;
/// **What it does:** This lint checks for usage of `Box<T>` where an unboxed `T` would work fine. It is `Warn` by default.
/// **What it does:** This lint checks for usage of `Box<T>` where an unboxed `T` would work fine.
///
/// **Why is this bad?** This is an unnecessary allocation, and bad for performance. It is only necessary to allocate if you wish to move the box into something.
///
@ -29,7 +29,9 @@ pub struct EscapePass;
/// println!("{}", *x);
/// }
/// ```
declare_lint!(pub BOXED_LOCAL, Warn, "using Box<T> where unnecessary");
declare_lint! {
pub BOXED_LOCAL, Warn, "using Box<T> where unnecessary"
}
fn is_non_trait_box(ty: ty::Ty) -> bool {
match ty.sty {

View file

@ -9,15 +9,17 @@ use utils::{snippet_opt, span_lint_and_then, is_adjusted};
pub struct EtaPass;
/// **What it does:** This lint checks for closures which just call another function where the function can be called directly. `unsafe` functions or calls where types get adjusted are ignored. It is `Warn` by default.
/// **What it does:** This lint checks for closures which just call another function where the function can be called directly. `unsafe` functions or calls where types get adjusted are ignored.
///
/// **Why is this bad?** Needlessly creating a closure just costs heap space and adds code for no benefit.
///
/// **Known problems:** None
///
/// **Example:** `xs.map(|x| foo(x))` where `foo(_)` is a plain function that takes the exact argument type of `x`.
declare_lint!(pub REDUNDANT_CLOSURE, Warn,
"using redundant closures, i.e. `|a| foo(a)` (which can be written as just `foo`)");
declare_lint! {
pub REDUNDANT_CLOSURE, Warn,
"using redundant closures, i.e. `|a| foo(a)` (which can be written as just `foo`)"
}
impl LintPass for EtaPass {
fn get_lints(&self) -> LintArray {

View file

@ -5,15 +5,17 @@ use syntax::codemap::Span;
use consts::{constant_simple, is_negative, Constant};
use utils::{span_lint, snippet, in_macro};
/// **What it does:** This lint checks for identity operations, e.g. `x + 0`. It is `Warn` by default.
/// **What it does:** This lint checks for identity operations, e.g. `x + 0`.
///
/// **Why is this bad?** This code can be removed without changing the meaning. So it just obscures what's going on. Delete it mercilessly.
///
/// **Known problems:** None
///
/// **Example:** `x / 1 + 0 * 1 - 0 | 0`
declare_lint! { pub IDENTITY_OP, Warn,
"using identity operations, e.g. `x + 0` or `y / 1`" }
declare_lint! {
pub IDENTITY_OP, Warn,
"using identity operations, e.g. `x + 0` or `y / 1`"
}
#[derive(Copy,Clone)]
pub struct IdentityOp;

View file

@ -5,8 +5,7 @@ use syntax::attr::*;
use syntax::ast::*;
use utils::in_macro;
/// **What it does:** It `Warn`s on blocks where there are items that are declared in the middle of
/// or after the statements
/// **What it does:** This lints checks for items declared after some statement in a block
///
/// **Why is this bad?** Items live for the entire scope they are declared in. But statements are
/// processed in order. This might cause confusion as it's hard to figure out which item is meant
@ -27,7 +26,11 @@ use utils::in_macro;
/// foo(); // prints "foo"
/// }
/// ```
declare_lint! { pub ITEMS_AFTER_STATEMENTS, Warn, "finds blocks where an item comes after a statement" }
declare_lint! {
pub ITEMS_AFTER_STATEMENTS,
Warn,
"finds blocks where an item comes after a statement"
}
pub struct ItemsAfterStatemets;

View file

@ -11,18 +11,20 @@ use syntax::ast::Lit;
use utils::{get_item_name, snippet, span_lint, walk_ptrs_ty};
/// **What it does:** This lint checks for getting the length of something via `.len()` just to compare to zero, and suggests using `.is_empty()` where applicable. It is `Warn` by default.
/// **What it does:** This lint checks for getting the length of something via `.len()` just to compare to zero, and suggests using `.is_empty()` where applicable.
///
/// **Why is this bad?** Some structures can answer `.is_empty()` much faster than calculating their length. So it is good to get into the habit of using `.is_empty()`, and having it is cheap. Besides, it makes the intent clearer than a comparison.
///
/// **Known problems:** None
///
/// **Example:** `if x.len() == 0 { .. }`
declare_lint!(pub LEN_ZERO, Warn,
"checking `.len() == 0` or `.len() > 0` (or similar) when `.is_empty()` \
could be used instead");
declare_lint! {
pub LEN_ZERO, Warn,
"checking `.len() == 0` or `.len() > 0` (or similar) when `.is_empty()` \
could be used instead"
}
/// **What it does:** This lint checks for items that implement `.len()` but not `.is_empty()`. It is `Warn` by default.
/// **What it does:** This lint checks for items that implement `.len()` but not `.is_empty()`.
///
/// **Why is this bad?** It is good custom to have both methods, because for some data structures, asking about the length will be a costly operation, whereas `.is_empty()` can usually answer in constant time. Also it used to lead to false positives on the [`len_zero`](#len_zero) lint currently that lint will ignore such entities.
///
@ -34,8 +36,10 @@ declare_lint!(pub LEN_ZERO, Warn,
/// fn len(&self) -> usize { .. }
/// }
/// ```
declare_lint!(pub LEN_WITHOUT_IS_EMPTY, Warn,
"traits and impls that have `.len()` but not `.is_empty()`");
declare_lint! {
pub LEN_WITHOUT_IS_EMPTY, Warn,
"traits and impls that have `.len()` but not `.is_empty()`"
}
#[derive(Copy,Clone)]
pub struct LenZero;

View file

@ -8,26 +8,32 @@ use std::collections::{HashSet, HashMap};
use utils::{in_external_macro, span_lint};
/// **What it does:** This lint checks for lifetime annotations which can be removed by relying on lifetime elision. It is `Warn` by default.
/// **What it does:** This lint checks for lifetime annotations which can be removed by relying on lifetime elision.
///
/// **Why is this bad?** The additional lifetimes make the code look more complicated, while there is nothing out of the ordinary going on. Removing them leads to more readable code.
///
/// **Known problems:** Potential false negatives: we bail out if the function has a `where` clause where lifetimes are mentioned.
///
/// **Example:** `fn in_and_out<'a>(x: &'a u8, y: u8) -> &'a u8 { x }`
declare_lint!(pub NEEDLESS_LIFETIMES, Warn,
"using explicit lifetimes for references in function arguments when elision rules \
would allow omitting them");
declare_lint! {
pub NEEDLESS_LIFETIMES,
Warn,
"using explicit lifetimes for references in function arguments when elision rules \
would allow omitting them"
}
/// **What it does:** This lint checks for lifetimes in generics that are never used anywhere else. It is `Warn` by default.
/// **What it does:** This lint checks for lifetimes in generics that are never used anywhere else.
///
/// **Why is this bad?** The additional lifetimes make the code look more complicated, while there is nothing out of the ordinary going on. Removing them leads to more readable code.
///
/// **Known problems:** None
///
/// **Example:** `fn unused_lifetime<'a>(x: u8) { .. }`
declare_lint!(pub UNUSED_LIFETIMES, Warn,
"unused lifetimes in function definitions");
declare_lint! {
pub UNUSED_LIFETIMES,
Warn,
"unused lifetimes in function definitions"
}
#[derive(Copy,Clone)]
pub struct LifetimePass;

View file

@ -13,7 +13,7 @@ use utils::{snippet, span_lint, get_parent_expr, match_trait_method, match_type,
span_help_and_lint, is_integer_literal, get_enclosing_block, span_lint_and_then, walk_ptrs_ty};
use utils::{BTREEMAP_PATH, HASHMAP_PATH, LL_PATH, OPTION_PATH, RESULT_PATH, VEC_PATH};
/// **What it does:** This lint checks for looping over the range of `0..len` of some collection just to get the values by index. It is `Warn` by default.
/// **What it does:** This lint checks for looping over the range of `0..len` of some collection just to get the values by index.
///
/// **Why is this bad?** Just iterating the collection itself makes the intent more clear and is probably faster.
///
@ -25,50 +25,65 @@ use utils::{BTREEMAP_PATH, HASHMAP_PATH, LL_PATH, OPTION_PATH, RESULT_PATH, VEC_
/// println!("{}", vec[i]);
/// }
/// ```
declare_lint!{ pub NEEDLESS_RANGE_LOOP, Warn,
"for-looping over a range of indices where an iterator over items would do" }
declare_lint! {
pub NEEDLESS_RANGE_LOOP,
Warn,
"for-looping over a range of indices where an iterator over items would do"
}
/// **What it does:** This lint checks for loops on `x.iter()` where `&x` will do, and suggest the latter. It is `Warn` by default.
/// **What it does:** This lint checks for loops on `x.iter()` where `&x` will do, and suggest the latter.
///
/// **Why is this bad?** Readability.
///
/// **Known problems:** False negatives. We currently only warn on some known types.
///
/// **Example:** `for x in y.iter() { .. }` (where y is a `Vec` or slice)
declare_lint!{ pub EXPLICIT_ITER_LOOP, Warn,
"for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do" }
declare_lint! {
pub EXPLICIT_ITER_LOOP,
Warn,
"for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do"
}
/// **What it does:** This lint checks for loops on `x.next()`. It is `Warn` by default.
/// **What it does:** This lint checks for loops on `x.next()`.
///
/// **Why is this bad?** `next()` returns either `Some(value)` if there was a value, or `None` otherwise. The insidious thing is that `Option<_>` implements `IntoIterator`, so that possibly one value will be iterated, leading to some hard to find bugs. No one will want to write such code [except to win an Underhanded Rust Contest](https://www.reddit.com/r/rust/comments/3hb0wm/underhanded_rust_contest/cu5yuhr).
///
/// **Known problems:** None
///
/// **Example:** `for x in y.next() { .. }`
declare_lint!{ pub ITER_NEXT_LOOP, Warn,
"for-looping over `_.next()` which is probably not intended" }
declare_lint! {
pub ITER_NEXT_LOOP,
Warn,
"for-looping over `_.next()` which is probably not intended"
}
/// **What it does:** This lint checks for `for` loops over `Option` values. It is `Warn` by default.
/// **What it does:** This lint checks for `for` loops over `Option` values.
///
/// **Why is this bad?** Readability. This is more clearly expressed as an `if let`.
///
/// **Known problems:** None
///
/// **Example:** `for x in option { .. }`. This should be `if let Some(x) = option { .. }`.
declare_lint!{ pub FOR_LOOP_OVER_OPTION, Warn,
"for-looping over an `Option`, which is more clearly expressed as an `if let`" }
declare_lint! {
pub FOR_LOOP_OVER_OPTION,
Warn,
"for-looping over an `Option`, which is more clearly expressed as an `if let`"
}
/// **What it does:** This lint checks for `for` loops over `Result` values. It is `Warn` by default.
/// **What it does:** This lint checks for `for` loops over `Result` values.
///
/// **Why is this bad?** Readability. This is more clearly expressed as an `if let`.
///
/// **Known problems:** None
///
/// **Example:** `for x in result { .. }`. This should be `if let Ok(x) = result { .. }`.
declare_lint!{ pub FOR_LOOP_OVER_RESULT, Warn,
"for-looping over a `Result`, which is more clearly expressed as an `if let`" }
declare_lint! {
pub FOR_LOOP_OVER_RESULT,
Warn,
"for-looping over a `Result`, which is more clearly expressed as an `if let`"
}
/// **What it does:** This lint detects `loop + match` combinations that are easier written as a `while let` loop. It is `Warn` by default.
/// **What it does:** This lint detects `loop + match` combinations that are easier written as a `while let` loop.
///
/// **Why is this bad?** The `while let` loop is usually shorter and more readable
///
@ -89,57 +104,77 @@ declare_lint!{ pub FOR_LOOP_OVER_RESULT, Warn,
/// // .. do something with x
/// }
/// ```
declare_lint!{ pub WHILE_LET_LOOP, Warn,
"`loop { if let { ... } else break }` can be written as a `while let` loop" }
declare_lint! {
pub WHILE_LET_LOOP,
Warn,
"`loop { if let { ... } else break }` can be written as a `while let` loop"
}
/// **What it does:** This lint checks for using `collect()` on an iterator without using the result. It is `Warn` by default.
/// **What it does:** This lint checks for using `collect()` on an iterator without using the result.
///
/// **Why is this bad?** It is more idiomatic to use a `for` loop over the iterator instead.
///
/// **Known problems:** None
///
/// **Example:** `vec.iter().map(|x| /* some operation returning () */).collect::<Vec<_>>();`
declare_lint!{ pub UNUSED_COLLECT, Warn,
"`collect()`ing an iterator without using the result; this is usually better \
written as a for loop" }
declare_lint! {
pub UNUSED_COLLECT,
Warn,
"`collect()`ing an iterator without using the result; this is usually better \
written as a for loop"
}
/// **What it does:** This lint checks for loops over ranges `x..y` where both `x` and `y` are constant and `x` is greater or equal to `y`, unless the range is reversed or has a negative `.step_by(_)`. It is `Warn` by default.
/// **What it does:** This lint checks for loops over ranges `x..y` where both `x` and `y` are constant and `x` is greater or equal to `y`, unless the range is reversed or has a negative `.step_by(_)`.
///
/// **Why is it bad?** Such loops will either be skipped or loop until wrap-around (in debug code, this may `panic!()`). Both options are probably not intended.
///
/// **Known problems:** The lint cannot catch loops over dynamically defined ranges. Doing this would require simulating all possible inputs and code paths through the program, which would be complex and error-prone.
///
/// **Examples**: `for x in 5..10-5 { .. }` (oops, stray `-`)
declare_lint!{ pub REVERSE_RANGE_LOOP, Warn,
"Iterating over an empty range, such as `10..0` or `5..5`" }
declare_lint! {
pub REVERSE_RANGE_LOOP,
Warn,
"Iterating over an empty range, such as `10..0` or `5..5`"
}
/// **What it does:** This lint checks `for` loops over slices with an explicit counter and suggests the use of `.enumerate()`. It is `Warn` by default.
/// **What it does:** This lint checks `for` loops over slices with an explicit counter and suggests the use of `.enumerate()`.
///
/// **Why is it bad?** Not only is the version using `.enumerate()` more readable, the compiler is able to remove bounds checks which can lead to faster code in some instances.
///
/// **Known problems:** None.
///
/// **Example:** `for i in 0..v.len() { foo(v[i]); }` or `for i in 0..v.len() { bar(i, v[i]); }`
declare_lint!{ pub EXPLICIT_COUNTER_LOOP, Warn,
"for-looping with an explicit counter when `_.enumerate()` would do" }
declare_lint! {
pub EXPLICIT_COUNTER_LOOP,
Warn,
"for-looping with an explicit counter when `_.enumerate()` would do"
}
/// **What it does:** This lint checks for empty `loop` expressions. It is `Warn` by default.
/// **What it does:** This lint checks for empty `loop` expressions.
///
/// **Why is this bad?** Those busy loops burn CPU cycles without doing anything. Think of the environment and either block on something or at least make the thread sleep for some microseconds.
///
/// **Known problems:** None
///
/// **Example:** `loop {}`
declare_lint!{ pub EMPTY_LOOP, Warn, "empty `loop {}` detected" }
declare_lint! {
pub EMPTY_LOOP,
Warn,
"empty `loop {}` detected"
}
/// **What it does:** This lint checks for `while let` expressions on iterators. It is `Warn` by default.
/// **What it does:** This lint checks for `while let` expressions on iterators.
///
/// **Why is this bad?** Readability. A simple `for` loop is shorter and conveys the intent better.
///
/// **Known problems:** None
///
/// **Example:** `while let Some(val) = iter() { .. }`
declare_lint!{ pub WHILE_LET_ON_ITERATOR, Warn, "using a while-let loop instead of a for loop on an iterator" }
declare_lint! {
pub WHILE_LET_ON_ITERATOR,
Warn,
"using a while-let loop instead of a for loop on an iterator"
}
/// **What it does:** This warns when you iterate on a map (`HashMap` or `BTreeMap`) and ignore
/// either the keys or values.
@ -157,7 +192,11 @@ declare_lint!{ pub WHILE_LET_ON_ITERATOR, Warn, "using a while-let loop instead
/// ```rust
/// for k in map.keys() { .. }
/// ```
declare_lint!{ pub FOR_KV_MAP, Warn, "looping on a map using `iter` when `keys` or `values` would do" }
declare_lint! {
pub FOR_KV_MAP,
Warn,
"looping on a map using `iter` when `keys` or `values` would do"
}
#[derive(Copy, Clone)]
pub struct LoopsPass;

View file

@ -4,16 +4,18 @@ use utils::{CLONE_PATH, OPTION_PATH};
use utils::{is_adjusted, match_path, match_trait_method, match_type, snippet, span_help_and_lint};
use utils::{walk_ptrs_ty, walk_ptrs_ty_depth};
/// **What it does:** This lint checks for mapping clone() over an iterator. It is `Warn` by default and suggests to use `.cloned()` instead.
/// **What it does:** This lint checks for mapping clone() over an iterator.
///
/// **Why is this bad?** It makes the code less readable.
///
/// **Known problems:** None
///
/// **Example:** `x.map(|e| e.clone());`
declare_lint!(pub MAP_CLONE, Warn,
"using `.map(|x| x.clone())` to clone an iterator or option's contents (recommends \
`.cloned()` instead)");
declare_lint! {
pub MAP_CLONE, Warn,
"using `.map(|x| x.clone())` to clone an iterator or option's contents (recommends \
`.cloned()` instead)"
}
#[derive(Copy, Clone)]
pub struct MapClonePass;

View file

@ -11,7 +11,7 @@ use syntax::codemap::Span;
use utils::{COW_PATH, OPTION_PATH, RESULT_PATH};
use utils::{match_type, snippet, span_lint, span_note_and_lint, span_lint_and_then, in_external_macro, expr_block};
/// **What it does:** This lint checks for matches with a single arm where an `if let` will usually suffice. It is `Warn` by default.
/// **What it does:** This lint checks for matches with a single arm where an `if let` will usually suffice.
///
/// **Why is this bad?** Just readability `if let` nests less than a `match`.
///
@ -24,11 +24,13 @@ use utils::{match_type, snippet, span_lint, span_note_and_lint, span_lint_and_th
/// _ => ()
/// }
/// ```
declare_lint!(pub SINGLE_MATCH, Warn,
"a match statement with a single nontrivial arm (i.e, where the other arm \
is `_ => {}`) is used; recommends `if let` instead");
declare_lint! {
pub SINGLE_MATCH, Warn,
"a match statement with a single nontrivial arm (i.e, where the other arm \
is `_ => {}`) is used; recommends `if let` instead"
}
/// **What it does:** This lint checks for matches with a two arms where an `if let` will usually suffice. It is `Allow` by default.
/// **What it does:** This lint checks for matches with a two arms where an `if let` will usually suffice.
///
/// **Why is this bad?** Just readability `if let` nests less than a `match`.
///
@ -41,11 +43,13 @@ declare_lint!(pub SINGLE_MATCH, Warn,
/// _ => bar(other_ref),
/// }
/// ```
declare_lint!(pub SINGLE_MATCH_ELSE, Allow,
"a match statement with a two arms where the second arm's pattern is a wildcard; \
recommends `if let` instead");
declare_lint! {
pub SINGLE_MATCH_ELSE, Allow,
"a match statement with a two arms where the second arm's pattern is a wildcard; \
recommends `if let` instead"
}
/// **What it does:** This lint checks for matches where all arms match a reference, suggesting to remove the reference and deref the matched expression instead. It also checks for `if let &foo = bar` blocks. It is `Warn` by default.
/// **What it does:** This lint checks for matches where all arms match a reference, suggesting to remove the reference and deref the matched expression instead. It also checks for `if let &foo = bar` blocks.
///
/// **Why is this bad?** It just makes the code less readable. That reference destructuring adds nothing to the code.
///
@ -60,11 +64,13 @@ declare_lint!(pub SINGLE_MATCH_ELSE, Allow,
/// _ => frob(&x),
/// }
/// ```
declare_lint!(pub MATCH_REF_PATS, Warn,
"a match or `if let` has all arms prefixed with `&`; the match expression can be \
dereferenced instead");
declare_lint! {
pub MATCH_REF_PATS, Warn,
"a match or `if let` has all arms prefixed with `&`; the match expression can be \
dereferenced instead"
}
/// **What it does:** This lint checks for matches where match expression is a `bool`. It suggests to replace the expression with an `if...else` block. It is `Warn` by default.
/// **What it does:** This lint checks for matches where match expression is a `bool`. It suggests to replace the expression with an `if...else` block.
///
/// **Why is this bad?** It makes the code less readable.
///
@ -79,10 +85,12 @@ declare_lint!(pub MATCH_REF_PATS, Warn,
/// false => bar(),
/// }
/// ```
declare_lint!(pub MATCH_BOOL, Warn,
"a match on boolean expression; recommends `if..else` block instead");
declare_lint! {
pub MATCH_BOOL, Warn,
"a match on boolean expression; recommends `if..else` block instead"
}
/// **What it does:** This lint checks for overlapping match arms. It is `Warn` by default.
/// **What it does:** This lint checks for overlapping match arms.
///
/// **Why is this bad?** It is likely to be an error and if not, makes the code less obvious.
///
@ -98,8 +106,9 @@ declare_lint!(pub MATCH_BOOL, Warn,
/// _ => (),
/// }
/// ```
declare_lint!(pub MATCH_OVERLAPPING_ARM, Warn,
"a match has overlapping arms");
declare_lint! {
pub MATCH_OVERLAPPING_ARM, Warn, "a match has overlapping arms"
}
#[allow(missing_copy_implementations)]
pub struct MatchPass;

View file

@ -18,17 +18,19 @@ use rustc::middle::cstore::CrateStore;
#[derive(Clone)]
pub struct MethodsPass;
/// **What it does:** This lint checks for `.unwrap()` calls on `Option`s. It is `Allow` by default.
/// **What it does:** This lint checks for `.unwrap()` calls on `Option`s.
///
/// **Why is this bad?** Usually it is better to handle the `None` case, or to at least call `.expect(_)` with a more helpful message. Still, for a lot of quick-and-dirty code, `unwrap` is a good choice, which is why this lint is `Allow` by default.
///
/// **Known problems:** None
///
/// **Example:** `x.unwrap()`
declare_lint!(pub OPTION_UNWRAP_USED, Allow,
"using `Option.unwrap()`, which should at least get a better message using `expect()`");
declare_lint! {
pub OPTION_UNWRAP_USED, Allow,
"using `Option.unwrap()`, which should at least get a better message using `expect()`"
}
/// **What it does:** This lint checks for `.unwrap()` calls on `Result`s. It is `Allow` by default.
/// **What it does:** This lint checks for `.unwrap()` calls on `Result`s.
///
/// **Why is this bad?** `result.unwrap()` will let the thread panic on `Err` values. Normally, you want to implement more sophisticated error handling, and propagate errors upwards with `try!`.
///
@ -37,20 +39,24 @@ declare_lint!(pub OPTION_UNWRAP_USED, Allow,
/// **Known problems:** None
///
/// **Example:** `x.unwrap()`
declare_lint!(pub RESULT_UNWRAP_USED, Allow,
"using `Result.unwrap()`, which might be better handled");
declare_lint! {
pub RESULT_UNWRAP_USED, Allow,
"using `Result.unwrap()`, which might be better handled"
}
/// **What it does:** This lint checks for `.to_string()` method calls on values of type `&str`. It is `Warn` by default.
/// **What it does:** This lint checks for `.to_string()` method calls on values of type `&str`.
///
/// **Why is this bad?** This uses the whole formatting machinery just to clone a string. Using `.to_owned()` is lighter on resources. You can also consider using a [`Cow<'a, str>`](http://doc.rust-lang.org/std/borrow/enum.Cow.html) instead in some cases.
///
/// **Known problems:** None
///
/// **Example:** `s.to_string()` where `s: &str`
declare_lint!(pub STR_TO_STRING, Warn,
"using `to_string()` on a str, which should be `to_owned()`");
declare_lint! {
pub STR_TO_STRING, Warn,
"using `to_string()` on a str, which should be `to_owned()`"
}
/// **What it does:** This lint checks for `.to_string()` method calls on values of type `String`. It is `Warn` by default.
/// **What it does:** This lint checks for `.to_string()` method calls on values of type `String`.
///
/// **Why is this bad?** This is an non-efficient way to clone a `String`, `.clone()` should be used
/// instead. `String` implements `ToString` mostly for generics.
@ -58,10 +64,12 @@ declare_lint!(pub STR_TO_STRING, Warn,
/// **Known problems:** None
///
/// **Example:** `s.to_string()` where `s: String`
declare_lint!(pub STRING_TO_STRING, Warn,
"calling `String::to_string` which is inefficient");
declare_lint! {
pub STRING_TO_STRING, Warn,
"calling `String::to_string` which is inefficient"
}
/// **What it does:** This lint checks for methods that should live in a trait implementation of a `std` trait (see [llogiq's blog post](http://llogiq.github.io/2015/07/30/traits.html) for further information) instead of an inherent implementation. It is `Warn` by default.
/// **What it does:** This lint checks for methods that should live in a trait implementation of a `std` trait (see [llogiq's blog post](http://llogiq.github.io/2015/07/30/traits.html) for further information) instead of an inherent implementation.
///
/// **Why is this bad?** Implementing the traits improve ergonomics for users of the code, often with very little cost. Also people seeing a `mul(..)` method may expect `*` to work equally, so you should have good reason to disappoint them.
///
@ -74,10 +82,12 @@ declare_lint!(pub STRING_TO_STRING, Warn,
/// fn add(&self, other: &X) -> X { .. }
/// }
/// ```
declare_lint!(pub SHOULD_IMPLEMENT_TRAIT, Warn,
"defining a method that should be implementing a std trait");
declare_lint! {
pub SHOULD_IMPLEMENT_TRAIT, Warn,
"defining a method that should be implementing a std trait"
}
/// **What it does:** This lint checks for methods with certain name prefixes and `Warn`s (by default) if the prefix doesn't match how self is taken. The actual rules are:
/// **What it does:** This lint checks for methods with certain name prefixes and which doesn't match how self is taken. The actual rules are:
///
/// |Prefix |`self` taken |
/// |-------|--------------------|
@ -87,7 +97,7 @@ declare_lint!(pub SHOULD_IMPLEMENT_TRAIT, Warn,
/// |`is_` |`&self` or none |
/// |`to_` |`&self` |
///
/// **Why is this bad?** Consistency breeds readability. If you follow the conventions, your users won't be surprised that they e.g. need to supply a mutable reference to a `as_`.. function.
/// **Why is this bad?** Consistency breeds readability. If you follow the conventions, your users won't be surprised that they e.g. need to supply a mutable reference to a `as_..` function.
///
/// **Known problems:** None
///
@ -98,11 +108,13 @@ declare_lint!(pub SHOULD_IMPLEMENT_TRAIT, Warn,
/// fn as_str(self) -> &str { .. }
/// }
/// ```
declare_lint!(pub WRONG_SELF_CONVENTION, Warn,
"defining a method named with an established prefix (like \"into_\") that takes \
`self` with the wrong convention");
declare_lint! {
pub WRONG_SELF_CONVENTION, Warn,
"defining a method named with an established prefix (like \"into_\") that takes \
`self` with the wrong convention"
}
/// **What it does:** This is the same as [`wrong_self_convention`](#wrong_self_convention), but for public items. This lint is `Allow` by default.
/// **What it does:** This is the same as [`wrong_self_convention`](#wrong_self_convention), but for public items.
///
/// **Why is this bad?** See [`wrong_self_convention`](#wrong_self_convention).
///
@ -114,31 +126,37 @@ declare_lint!(pub WRONG_SELF_CONVENTION, Warn,
/// pub fn as_str(self) -> &str { .. }
/// }
/// ```
declare_lint!(pub WRONG_PUB_SELF_CONVENTION, Allow,
"defining a public method named with an established prefix (like \"into_\") that takes \
`self` with the wrong convention");
declare_lint! {
pub WRONG_PUB_SELF_CONVENTION, Allow,
"defining a public method named with an established prefix (like \"into_\") that takes \
`self` with the wrong convention"
}
/// **What it does:** This lint `Warn`s on using `ok().expect(..)`.
/// **What it does:** This lint checks for usage of `ok().expect(..)`.
///
/// **Why is this bad?** Because you usually call `expect()` on the `Result` directly to get a good error message.
///
/// **Known problems:** None.
///
/// **Example:** `x.ok().expect("why did I do this again?")`
declare_lint!(pub OK_EXPECT, Warn,
"using `ok().expect()`, which gives worse error messages than \
calling `expect` directly on the Result");
declare_lint! {
pub OK_EXPECT, Warn,
"using `ok().expect()`, which gives worse error messages than \
calling `expect` directly on the Result"
}
/// **What it does:** This lint `Warn`s on `_.map(_).unwrap_or(_)`.
/// **What it does:** This lint checks for usage of `_.map(_).unwrap_or(_)`.
///
/// **Why is this bad?** Readability, this can be written more concisely as `_.map_or(_, _)`.
///
/// **Known problems:** None.
///
/// **Example:** `x.map(|a| a + 1).unwrap_or(0)`
declare_lint!(pub OPTION_MAP_UNWRAP_OR, Warn,
"using `Option.map(f).unwrap_or(a)`, which is more succinctly expressed as \
`map_or(a, f)`");
declare_lint! {
pub OPTION_MAP_UNWRAP_OR, Warn,
"using `Option.map(f).unwrap_or(a)`, which is more succinctly expressed as \
`map_or(a, f)`"
}
/// **What it does:** This lint `Warn`s on `_.map(_).unwrap_or_else(_)`.
///
@ -147,9 +165,11 @@ declare_lint!(pub OPTION_MAP_UNWRAP_OR, Warn,
/// **Known problems:** None.
///
/// **Example:** `x.map(|a| a + 1).unwrap_or_else(some_function)`
declare_lint!(pub OPTION_MAP_UNWRAP_OR_ELSE, Warn,
"using `Option.map(f).unwrap_or_else(g)`, which is more succinctly expressed as \
`map_or_else(g, f)`");
declare_lint! {
pub OPTION_MAP_UNWRAP_OR_ELSE, Warn,
"using `Option.map(f).unwrap_or_else(g)`, which is more succinctly expressed as \
`map_or_else(g, f)`"
}
/// **What it does:** This lint `Warn`s on `_.filter(_).next()`.
///
@ -158,8 +178,10 @@ declare_lint!(pub OPTION_MAP_UNWRAP_OR_ELSE, Warn,
/// **Known problems:** None.
///
/// **Example:** `iter.filter(|x| x == 0).next()`
declare_lint!(pub FILTER_NEXT, Warn,
"using `filter(p).next()`, which is more succinctly expressed as `.find(p)`");
declare_lint! {
pub FILTER_NEXT, Warn,
"using `filter(p).next()`, which is more succinctly expressed as `.find(p)`"
}
/// **What it does:** This lint `Warn`s on an iterator search (such as `find()`, `position()`, or
/// `rposition()`) followed by a call to `is_some()`.
@ -169,9 +191,11 @@ declare_lint!(pub FILTER_NEXT, Warn,
/// **Known problems:** None.
///
/// **Example:** `iter.find(|x| x == 0).is_some()`
declare_lint!(pub SEARCH_IS_SOME, Warn,
"using an iterator search followed by `is_some()`, which is more succinctly \
expressed as a call to `any()`");
declare_lint! {
pub SEARCH_IS_SOME, Warn,
"using an iterator search followed by `is_some()`, which is more succinctly \
expressed as a call to `any()`"
}
/// **What it does:** This lint `Warn`s on using `.chars().next()` on a `str` to check if it
/// starts with a given char.
@ -181,8 +205,10 @@ declare_lint!(pub SEARCH_IS_SOME, Warn,
/// **Known problems:** None.
///
/// **Example:** `name.chars().next() == Some('_')`
declare_lint!(pub CHARS_NEXT_CMP, Warn,
"using `.chars().next()` to check if a string starts with a char");
declare_lint! {
pub CHARS_NEXT_CMP, Warn,
"using `.chars().next()` to check if a string starts with a char"
}
/// **What it does:** This lint checks for calls to `.or(foo(..))`, `.unwrap_or(foo(..))`, etc., and
/// suggests to use `or_else`, `unwrap_or_else`, etc., or `unwrap_or_default` instead.
@ -203,18 +229,22 @@ declare_lint!(pub CHARS_NEXT_CMP, Warn,
///
/// **Known problems:** If the function as side-effects, not calling it will change the semantic of
/// the program, but you shouldn't rely on that anyway.
declare_lint!(pub OR_FUN_CALL, Warn,
"using any `*or` method when the `*or_else` would do");
declare_lint! {
pub OR_FUN_CALL, Warn,
"using any `*or` method when the `*or_else` would do"
}
/// **What it does:** This lint `Warn`s on using `.extend(s)` on a `vec` to extend the vec by a slice.
/// **What it does:** This lint checks for usage of `.extend(s)` on a `Vec` to extend the vector by a slice.
///
/// **Why is this bad?** Since Rust 1.6, the `extend_from_slice(_)` method is stable and at least for now faster.
///
/// **Known problems:** None.
///
/// **Example:** `my_vec.extend(&xs)`
declare_lint!(pub EXTEND_FROM_SLICE, Warn,
"`.extend_from_slice(_)` is a faster way to extend a Vec by a slice");
declare_lint! {
pub EXTEND_FROM_SLICE, Warn,
"`.extend_from_slice(_)` is a faster way to extend a Vec by a slice"
}
/// **What it does:** This lint warns on using `.clone()` on a `Copy` type.
///
@ -224,8 +254,9 @@ declare_lint!(pub EXTEND_FROM_SLICE, Warn,
/// **Known problems:** None.
///
/// **Example:** `42u64.clone()`
declare_lint!(pub CLONE_ON_COPY, Warn,
"using `clone` on a `Copy` type");
declare_lint! {
pub CLONE_ON_COPY, Warn, "using `clone` on a `Copy` type"
}
/// **What it does:** This lint warns on using `.clone()` on an `&&T`
///
@ -244,8 +275,9 @@ declare_lint!(pub CLONE_ON_COPY, Warn,
/// }
/// ```
///
declare_lint!(pub CLONE_DOUBLE_REF, Warn,
"using `clone` on `&&T`");
declare_lint! {
pub CLONE_DOUBLE_REF, Warn, "using `clone` on `&&T`"
}
impl LintPass for MethodsPass {
fn get_lints(&self) -> LintArray {

View file

@ -8,16 +8,17 @@ use consts::{Constant, constant_simple};
use utils::{match_def_path, span_lint};
use self::MinMax::{Min, Max};
/// **What it does:** This lint checks for expressions where `std::cmp::min` and `max` are used to clamp values, but switched so that the result is constant. It is `Warn` by default.
/// **What it does:** This lint checks for expressions where `std::cmp::min` and `max` are used 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 the least it hurts readability of the code.
///
/// **Known problems:** None
///
/// **Example:** `min(0, max(100, x))` will always be equal to `0`. Probably the author meant to clamp the value between 0 and 100, but has erroneously swapped `min` and `max`.
declare_lint!(pub MIN_MAX, Warn,
"`min(_, max(_, _))` (or vice versa) with bounds clamping the result \
to a constant");
declare_lint! {
pub MIN_MAX, Warn,
"`min(_, max(_, _))` (or vice versa) with bounds clamping the result to a constant"
}
#[allow(missing_copy_implementations)]
pub struct MinMaxPass;

View file

@ -13,7 +13,7 @@ use rustc::middle::const_eval::EvalHint::ExprTypeChecked;
use utils::{get_item_name, match_path, snippet, get_parent_expr, span_lint};
use utils::{span_help_and_lint, walk_ptrs_ty, is_integer_literal, implements_trait};
/// **What it does:** This lint checks for function arguments and let bindings denoted as `ref`. It is `Warn` by default.
/// **What it does:** This lint checks for function arguments and let bindings denoted as `ref`.
///
/// **Why is this bad?** The `ref` declaration makes the function take an owned value, but turns the argument into a reference (which means that the value is destroyed when exiting the function). This adds not much value: either take a reference type, or take an owned value and create references in the body.
///
@ -22,10 +22,12 @@ use utils::{span_help_and_lint, walk_ptrs_ty, is_integer_literal, implements_tra
/// **Known problems:** If the argument is dereferenced within the function, removing the `ref` will lead to errors. This can be fixed by removing the dereferences, e.g. changing `*x` to `x` within the function.
///
/// **Example:** `fn foo(ref x: u8) -> bool { .. }`
declare_lint!(pub 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 `&`.");
declare_lint! {
pub 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 `&`."
}
#[allow(missing_copy_implementations)]
pub struct TopLevelRefPass;
@ -76,7 +78,7 @@ impl LateLintPass for TopLevelRefPass {
}
}
/// **What it does:** This lint checks for comparisons to NAN. It is `Deny` by default.
/// **What it does:** This lint checks for comparisons to NAN.
///
/// **Why is this bad?** NAN does not compare meaningfully to anything not even itself so those comparisons are simply wrong.
///
@ -121,7 +123,7 @@ fn check_nan(cx: &LateContext, path: &Path, span: Span) {
});
}
/// **What it does:** This lint checks for (in-)equality comparisons on floating-point values (apart from zero), except in functions called `*eq*` (which probably implement equality for a type involving floats). It is `Warn` by default.
/// **What it does:** This lint checks for (in-)equality comparisons on floating-point values (apart from zero), except in functions called `*eq*` (which probably implement equality for a type involving floats).
///
/// **Why is this bad?** Floating point calculations are usually imprecise, so asking if two values are *exactly* equal is asking for trouble. For a good guide on what to do, see [the floating point guide](http://www.floating-point-gui.de/errors/comparison).
///
@ -187,7 +189,7 @@ fn is_float(cx: &LateContext, expr: &Expr) -> bool {
}
}
/// **What it does:** This lint checks for conversions to owned values just for the sake of a comparison. It is `Warn` by default.
/// **What it does:** This lint checks for conversions to owned values just for the sake of a comparison.
///
/// **Why is this bad?** The comparison can operate on a reference, so creating an owned value effectively throws it away directly afterwards, which is needlessly consuming code and heap space.
///
@ -281,7 +283,7 @@ fn is_str_arg(cx: &LateContext, args: &[P<Expr>]) -> bool {
}
}
/// **What it does:** This lint checks for getting the remainder of a division by one. It is `Warn` by default.
/// **What it does:** This lint 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 such code deliberately, unless trying to win an Underhanded Rust Contest. Even for that contest, it's probably a bad idea. Use something more underhanded.
///
@ -311,7 +313,7 @@ impl LateLintPass for ModuloOne {
}
}
/// **What it does:** This lint checks for patterns in the form `name @ _`. It is `Warn` by default.
/// **What it does:** This lint checks for patterns in the form `name @ _`.
///
/// **Why is this bad?** It's almost always more readable to just use direct bindings.
///

View file

@ -8,25 +8,29 @@ use syntax::visit::FnKind;
use utils::{span_lint, span_help_and_lint};
/// **What it does:** This lint `Warn`s on struct field patterns bound to wildcards.
/// **What it does:** This lint checks for structure field patterns bound to wildcards.
///
/// **Why is this bad?** Using `..` instead is shorter and leaves the focus on the fields that are actually bound.
///
/// **Known problems:** None.
///
/// **Example:** `let { a: _, b: ref b, c: _ } = ..`
declare_lint!(pub UNNEEDED_FIELD_PATTERN, Warn,
"Struct fields are bound to a wildcard instead of using `..`");
declare_lint! {
pub UNNEEDED_FIELD_PATTERN, Warn,
"Struct fields are bound to a wildcard instead of using `..`"
}
/// **What it does:** This lint `Warn`s on function arguments having the similar names differing by an underscore
/// **What it does:** This lint checks for function arguments having the similar names differing by an underscore
///
/// **Why is this bad?** It affects code readability
///
/// **Known problems:** None.
///
/// **Example:** `fn foo(a: i32, _a: i32) {}`
declare_lint!(pub DUPLICATE_UNDERSCORE_ARGUMENT, Warn,
"Function arguments having names which only differ by an underscore");
declare_lint! {
pub DUPLICATE_UNDERSCORE_ARGUMENT, Warn,
"Function arguments having names which only differ by an underscore"
}
#[derive(Copy, Clone)]
pub struct MiscEarly;

View file

@ -4,16 +4,19 @@ use rustc::middle::ty::{TypeAndMut, TyRef};
use utils::{in_external_macro, span_lint};
/// **What it does:** This lint checks for instances of `mut mut` references. It is `Warn` by default.
/// **What it does:** This lint checks for instances of `mut mut` references.
///
/// **Why is this bad?** Multiple `mut`s don't add anything meaningful to the source.
///
/// **Known problems:** None
///
/// **Example:** `let x = &mut &mut y;`
declare_lint!(pub MUT_MUT, Allow,
"usage of double-mut refs, e.g. `&mut &mut ...` (either copy'n'paste error, \
or shows a fundamental misunderstanding of references)");
declare_lint! {
pub MUT_MUT,
Allow,
"usage of double-mut refs, e.g. `&mut &mut ...` (either copy'n'paste error, \
or shows a fundamental misunderstanding of references)"
}
#[derive(Copy,Clone)]
pub struct MutMut;

View file

@ -4,7 +4,7 @@ use utils::span_lint;
use rustc::middle::ty::{TypeAndMut, TypeVariants, MethodCall, TyS};
use syntax::ptr::P;
/// **What it does:** This lint detects giving a mutable reference to a function that only requires an immutable reference. It is `Warn` by default.
/// **What it does:** This lint detects giving a mutable reference to a function that only requires an immutable reference.
///
/// **Why is this bad?** The immutable reference rules out all other references to the value. Also the code misleads about the intent of the call site.
///

View file

@ -11,7 +11,7 @@ use rustc::middle::subst::ParamSpace;
use utils::{span_lint, MUTEX_PATH, match_type};
/// **What it does:** It `Warn`s on usages of `Mutex<X>` where an atomic will do
/// **What it does:** This lint checks for usages of `Mutex<X>` where an atomic will do.
///
/// **Why is this bad?** Using a Mutex just to make access to a plain bool or reference sequential is shooting flies with cannons. `std::atomic::AtomicBool` and `std::atomic::AtomicPtr` are leaner and faster.
///
@ -24,7 +24,7 @@ declare_lint! {
"using a Mutex where an atomic value could be used instead"
}
/// **What it does:** It `Warn`s on usages of `Mutex<X>` where `X` is an integral type.
/// **What it does:** This lint checks for usages of `Mutex<X>` where `X` is an integral type.
///
/// **Why is this bad?** Using a Mutex just to make access to a plain integer sequential is shooting flies with cannons. `std::atomic::usize` is leaner and faster.
///

View file

@ -9,7 +9,7 @@ use syntax::ast::Lit_::*;
use utils::{span_lint, snippet};
/// **What it does:** This lint checks for expressions of the form `if c { true } else { false }` (or vice versa) and suggest using the condition directly. It is `Warn` by default.
/// **What it does:** This lint checks for expressions of the form `if c { true } else { false }` (or vice versa) and suggest using the condition directly.
///
/// **Why is this bad?** Redundant code.
///

View file

@ -8,7 +8,7 @@ use rustc_front::hir::*;
use utils::span_lint;
use utils;
/// **What it does:** This lint `Warn`s on use of the `as_slice(..)` function, which is unstable.
/// **What it does:** This lint checks for usage of the `as_slice(..)` function, which is unstable.
///
/// **Why is this bad?** Using this function doesn't make your code better, but it will preclude it from building with stable Rust.
///
@ -22,7 +22,7 @@ declare_lint! {
see https://github.com/rust-lang/rust/issues/27729"
}
/// **What it does:** This lint `Warn`s on use of the `as_mut_slice(..)` function, which is unstable.
/// **What it does:** This lint checks for usage of the `as_mut_slice(..)` function, which is unstable.
///
/// **Why is this bad?** Using this function doesn't make your code better, but it will preclude it from building with stable Rust.
///

View file

@ -4,7 +4,7 @@ use rustc_front::hir::{Expr, ExprStruct};
use utils::span_lint;
/// **What it does:** This lint `Warn`s on needlessly including a base struct on update when all fields are changed anyway.
/// **What it does:** This lint warns on needlessly including a base struct on update when all fields are changed anyway.
///
/// **Why is this bad?** This will cost resources (because the base has to be somewhere), and make the code less readable.
///

View file

@ -6,7 +6,7 @@ use rustc_front::hir::{Stmt, StmtSemi};
use utils::in_macro;
use utils::span_lint;
/// **What it does:** This lint `Warn`s on statements which have no effect.
/// **What it does:** This lint checks for statements which have no effect.
///
/// **Why is this bad?** Similar to dead code, these statements are actually executed. However, as they have no effect, all they do is make the code less readable.
///

View file

@ -4,7 +4,7 @@ use utils::{walk_ptrs_ty_depth, match_type, span_lint, OPEN_OPTIONS_PATH};
use syntax::codemap::{Span, Spanned};
use syntax::ast::Lit_::LitBool;
/// **What it does:** This lint checks for duplicate open options as well as combinations that make no sense. It is `Warn` by default.
/// **What it does:** This lint checks for duplicate open options as well as combinations that make no sense.
///
/// **Why is this bad?** In the best case, the code will be harder to read than necessary. I don't know the worst case.
///

View file

@ -4,16 +4,18 @@ use syntax::ast::Lit_::LitStr;
use utils::{span_lint, in_external_macro, match_path, BEGIN_UNWIND};
/// **What it does:** Warn about missing parameters in `panic!`.
/// **What it does:** This lint checks for missing parameters in `panic!`.
///
/// **Known problems:** Should you want to use curly brackets in `panic!` without any parameter,
/// this lint will warn.
///
/// **Example:**
/// ```
/// panic!("This panic! is probably missing a parameter there: {}");
/// panic!("This `panic!` is probably missing a parameter there: {}");
/// ```
declare_lint!(pub PANIC_PARAMS, Warn, "missing parameters in `panic!`");
declare_lint! {
pub PANIC_PARAMS, Warn, "missing parameters in `panic!`"
}
#[allow(missing_copy_implementations)]
pub struct PanicPass;

View file

@ -4,7 +4,7 @@ use syntax::ast::*;
use utils::{span_lint, snippet};
/// **What it does:** This lint checks for operations where precedence may be unclear and `Warn`s about them by default, suggesting to add parentheses. Currently it catches the following:
/// **What it does:** This lint checks for operations where precedence may be unclear and suggests to add parentheses. Currently it catches the following:
/// * mixed usage of arithmetic and bit shifting/combining operators without parentheses
/// * a "negative" numeric literal (which is really a unary `-` followed by a numeric literal) followed by a method call
///
@ -15,9 +15,11 @@ use utils::{span_lint, snippet};
/// **Examples:**
/// * `1 << 2 + 3` equals 32, while `(1 << 2) + 3` equals 7
/// * `-1i32.abs()` equals -1, while `(-1i32).abs()` equals 1
declare_lint!(pub PRECEDENCE, Warn,
"catches operations where precedence may be unclear. See the wiki for a \
list of cases caught");
declare_lint! {
pub PRECEDENCE, Warn,
"catches operations where precedence may be unclear. See the wiki for a \
list of cases caught"
}
#[derive(Copy,Clone)]
pub struct Precedence;

View file

@ -2,8 +2,7 @@ use rustc::lint::*;
use rustc_front::hir::*;
use utils::{IO_PRINT_PATH, is_expn_of, match_path, span_lint};
/// **What it does:** This lint warns whenever you print on *stdout*. This lint is `Allow` by
/// default, the purpose is to catch debugging remnants.
/// **What it does:** This lint warns whenever you print on *stdout*. The purpose of this lint is to catch debugging remnants.
///
/// **Why is this bad?** People often print on *stdout* while debugging an application and might
/// forget to remove those prints afterward.

View file

@ -10,7 +10,7 @@ use rustc::middle::ty;
use utils::{span_lint, match_type};
use utils::{STRING_PATH, VEC_PATH};
/// **What it does:** This lint checks for function arguments of type `&String` or `&Vec` unless the references are mutable. It is `Warn` by default.
/// **What it does:** This lint checks for function arguments of type `&String` or `&Vec` unless the references are mutable.
///
/// **Why is this bad?** Requiring the argument to be of the specific size makes the function less useful for no benefit; slices in the form of `&[T]` or `&str` usually suffice and can be obtained from other types, too.
///

View file

@ -3,7 +3,7 @@ use rustc_front::hir::*;
use syntax::codemap::Spanned;
use utils::{is_integer_literal, match_type, snippet};
/// **What it does:** This lint checks for iterating over ranges with a `.step_by(0)`, which never terminates. It is `Warn` by default.
/// **What it does:** This lint checks for iterating over ranges with a `.step_by(0)`, which never terminates.
///
/// **Why is this bad?** This very much looks like an oversight, since with `loop { .. }` there is an obvious better way to endlessly loop.
///
@ -14,7 +14,7 @@ declare_lint! {
pub RANGE_STEP_BY_ZERO, Warn,
"using Range::step_by(0), which produces an infinite iterator"
}
/// **What it does:** This lint checks for zipping a collection with the range of `0.._.len()`. It is `Warn` by default.
/// **What it does:** This lint checks for zipping a collection with the range of `0.._.len()`.
///
/// **Why is this bad?** The code is better expressed with `.enumerate()`.
///

View file

@ -10,7 +10,7 @@ use rustc::lint::*;
use utils::{match_path, REGEX_NEW_PATH, span_lint, span_help_and_lint};
/// **What it does:** This lint checks `Regex::new(_)` invocations for correct regex syntax. It is `deny` by default.
/// **What it does:** This lint checks `Regex::new(_)` invocations for correct regex syntax.
///
/// **Why is this bad?** This will lead to a runtime panic.
///

View file

@ -6,25 +6,30 @@ use syntax::visit::FnKind;
use utils::{span_lint, span_lint_and_then, snippet_opt, match_path_ast, in_external_macro};
/// **What it does:** This lint checks for return statements at the end of a block. It is `Warn` by default.
/// **What it does:** This lint checks for return statements at the end of a block.
///
/// **Why is this bad?** Removing the `return` and semicolon will make the code more rusty.
///
/// **Known problems:** None
///
/// **Example:** `fn foo(x: usize) { return x; }`
declare_lint!(pub NEEDLESS_RETURN, Warn,
"using a return statement like `return expr;` where an expression would suffice");
/// **What it does:** This lint checks for `let`-bindings, which are subsequently returned. It is `Warn` by default.
declare_lint! {
pub NEEDLESS_RETURN, Warn,
"using a return statement like `return expr;` where an expression would suffice"
}
/// **What it does:** This lint checks for `let`-bindings, which are subsequently returned.
///
/// **Why is this bad?** It is just extraneous code. Remove it to make your code more rusty.
///
/// **Known problems:** None
///
/// **Example:** `{ let x = ..; x }`
declare_lint!(pub LET_AND_RETURN, Warn,
"creating a let-binding and then immediately returning it like `let x = expr; x` at \
the end of a block");
declare_lint! {
pub LET_AND_RETURN, Warn,
"creating a let-binding and then immediately returning it like `let x = expr; x` at \
the end of a block"
}
#[derive(Copy, Clone)]
pub struct ReturnPass;

View file

@ -9,34 +9,42 @@ use rustc::middle::def::Def;
use utils::{is_from_for_desugar, in_external_macro, snippet, span_lint, span_note_and_lint, DiagnosticWrapper};
/// **What it does:** This lint checks for bindings that shadow other bindings already in scope, while just changing reference level or mutability. It is `Allow` by default.
/// **What it does:** This lint checks for bindings that shadow other bindings already in scope, while just changing reference level or mutability.
///
/// **Why is this bad?** Not much, in fact it's a very common pattern in Rust code. Still, some may opt to avoid it in their code base, they can set this lint to `Warn`.
///
/// **Known problems:** This lint, as the other shadowing related lints, currently only catches very simple patterns.
///
/// **Example:** `let x = &x;`
declare_lint!(pub SHADOW_SAME, Allow,
"rebinding a name to itself, e.g. `let mut x = &mut x`");
/// **What it does:** This lint checks for bindings that shadow other bindings already in scope, while reusing the original value. It is `Allow` by default.
declare_lint! {
pub SHADOW_SAME, Allow,
"rebinding a name to itself, e.g. `let mut x = &mut x`"
}
/// **What it does:** This lint checks for bindings that shadow other bindings already in scope, while reusing the original value.
///
/// **Why is this bad?** Not too much, in fact it's a common pattern in Rust code. Still, some argue that name shadowing like this hurts readability, because a value may be bound to different things depending on position in the code.
///
/// **Known problems:** This lint, as the other shadowing related lints, currently only catches very simple patterns.
///
/// **Example:** `let x = x + 1;`
declare_lint!(pub SHADOW_REUSE, Allow,
declare_lint! {
pub SHADOW_REUSE, Allow,
"rebinding a name to an expression that re-uses the original value, e.g. \
`let x = x + 1`");
/// **What it does:** This lint checks for bindings that shadow other bindings already in scope, either without a initialization or with one that does not even use the original value. This lint is `Warn` by default.
`let x = x + 1`"
}
/// **What it does:** This lint checks for bindings that shadow other bindings already in scope, either without a initialization or with one that does not even use the original value.
///
/// **Why is this bad?** Name shadowing can hurt readability, especially in large code bases, because it is easy to lose track of the active binding at any place in the code. This can be alleviated by either giving more specific names to bindings ore introducing more scopes to contain the bindings.
///
/// **Known problems:** This lint, as the other shadowing related lints, currently only catches very simple patterns.
///
/// **Example:** `let x = y; let x = z; // shadows the earlier binding`
declare_lint!(pub SHADOW_UNRELATED, Allow,
"The name is re-bound without even using the original value");
declare_lint! {
pub SHADOW_UNRELATED, Allow,
"The name is re-bound without even using the original value"
}
#[derive(Copy, Clone)]
pub struct ShadowPass;

View file

@ -10,7 +10,7 @@ use syntax::codemap::Spanned;
use utils::{is_exp_equal, match_type, span_lint, walk_ptrs_ty, get_parent_expr};
use utils::STRING_PATH;
/// **What it does:** This lint matches code of the form `x = x + y` (without `let`!). It is `Allow` by default.
/// **What it does:** This lint matches code of the form `x = x + y` (without `let`!).
///
/// **Why is this bad?** Because this expression needs another copy as opposed to `x.push_str(y)` (in practice LLVM will usually elide it, though). Despite [llogiq](https://github.com/llogiq)'s reservations, this lint also is `allow` by default, as some people opine that it's more readable.
///
@ -28,7 +28,7 @@ declare_lint! {
"using `x = x + ..` where x is a `String`; suggests using `push_str()` instead"
}
/// **What it does:** The `string_add` lint matches all instances of `x + _` where `x` is of type `String`, but only if [`string_add_assign`](#string_add_assign) does *not* match. It is `Allow` by default.
/// **What it does:** The `string_add` lint matches all instances of `x + _` where `x` is of type `String`, but only if [`string_add_assign`](#string_add_assign) does *not* match.
///
/// **Why is this bad?** It's not bad in and of itself. However, this particular `Add` implementation is asymmetric (the other operand need not be `String`, but `x` does), while addition as mathematically defined is symmetric, also the `String::push_str(_)` function is a perfectly good replacement. Therefore some dislike it and wish not to have it in their code.
///
@ -49,7 +49,7 @@ declare_lint! {
}
/// **What it does:** This lint matches the `as_bytes` method called on string
/// literals that contain only ascii characters. It is `Warn` by default.
/// literals that contain only ascii characters.
///
/// **Why is this bad?** Byte string literals (e.g. `b"foo"`) can be used instead. They are shorter but less discoverable than `as_bytes()`.
///

View file

@ -4,9 +4,9 @@ use rustc_front::hir::{Expr, ExprAssign, ExprField, ExprStruct, ExprTup, ExprTup
use utils::is_adjusted;
use utils::span_lint;
/// **What it does:** This lint `Warn`s on creating a struct or tuple just to assign a value in it.
/// **What it does:** This lint checks for construction of a structure or tuple just to assign a value in it.
///
/// **Why is this bad?** Readability. If the struct is only created to be updated, why not write the struct you want in the first place?
/// **Why is this bad?** Readability. If the structure is only created to be updated, why not write the structure you want in the first place?
///
/// **Known problems:** None.
///

View file

@ -2,7 +2,7 @@ use rustc::lint::*;
use rustc_front::hir::*;
use utils;
/// **What it does:** This lint checks for transmutes to the original type of the object. It is `Warn` by default.
/// **What it does:** This lint checks for transmutes to the original type of the object.
///
/// **Why is this bad?** Readability. The code tricks people into thinking that the original value was of some other type.
///

View file

@ -15,17 +15,19 @@ use utils::*;
#[allow(missing_copy_implementations)]
pub struct TypePass;
/// **What it does:** This lint checks for use of `Box<Vec<_>>` anywhere in the code. It is `Warn` by default.
/// **What it does:** This lint checks for use of `Box<Vec<_>>` anywhere in the code.
///
/// **Why is this bad?** `Vec` already keeps its contents in a separate area on the heap. So if you `Box` it, you just add another level of indirection without any benefit whatsoever.
///
/// **Known problems:** None
///
/// **Example:** `struct X { values: Box<Vec<Foo>> }`
declare_lint!(pub BOX_VEC, Warn,
"usage of `Box<Vec<T>>`, vector elements are already on the heap");
declare_lint! {
pub BOX_VEC, Warn,
"usage of `Box<Vec<T>>`, vector elements are already on the heap"
}
/// **What it does:** This lint checks for usage of any `LinkedList`, suggesting to use a `Vec` or a `VecDeque` (formerly called `RingBuf`). It is `Warn` by default.
/// **What it does:** This lint checks for usage of any `LinkedList`, suggesting to use a `Vec` or a `VecDeque` (formerly called `RingBuf`).
///
/// **Why is this bad?** Gankro says:
///
@ -36,9 +38,11 @@ declare_lint!(pub BOX_VEC, Warn,
/// **Known problems:** False positives the instances where using a `LinkedList` makes sense are few and far between, but they can still happen.
///
/// **Example:** `let x = LinkedList::new();`
declare_lint!(pub LINKEDLIST, Warn,
"usage of LinkedList, usually a vector is faster, or a more specialized data \
structure like a VecDeque");
declare_lint! {
pub LINKEDLIST, Warn,
"usage of LinkedList, usually a vector is faster, or a more specialized data \
structure like a VecDeque"
}
impl LintPass for TypePass {
fn get_lints(&self) -> LintArray {
@ -74,15 +78,17 @@ impl LateLintPass for TypePass {
#[allow(missing_copy_implementations)]
pub struct LetPass;
/// **What it does:** This lint checks for binding a unit value. It is `Warn` by default.
/// **What it does:** This lint checks for binding a unit value.
///
/// **Why is this bad?** A unit value cannot usefully be used anywhere. So binding one is kind of pointless.
///
/// **Known problems:** None
///
/// **Example:** `let x = { 1; };`
declare_lint!(pub LET_UNIT_VALUE, Warn,
"creating a let binding to a value of unit type, which usually can't be used afterwards");
declare_lint! {
pub LET_UNIT_VALUE, Warn,
"creating a let binding to a value of unit type, which usually can't be used afterwards"
}
fn check_let_unit(cx: &LateContext, decl: &Decl) {
if let DeclLocal(ref local) = decl.node {
@ -115,15 +121,17 @@ impl LateLintPass for LetPass {
}
}
/// **What it does:** This lint checks for comparisons to unit. It is `Warn` by default.
/// **What it does:** This lint checks for comparisons to unit.
///
/// **Why is this bad?** Unit is always equal to itself, and thus is just a clumsily written constant. Mostly this happens when someone accidentally adds semicolons at the end of the operands.
///
/// **Known problems:** None
///
/// **Example:** `if { foo(); } == { bar(); } { baz(); }` is equal to `{ foo(); bar(); baz(); }`
declare_lint!(pub UNIT_CMP, Warn,
"comparing unit values (which is always `true` or `false`, respectively)");
declare_lint! {
pub UNIT_CMP, Warn,
"comparing unit values (which is always `true` or `false`, respectively)"
}
#[allow(missing_copy_implementations)]
pub struct UnitCmp;
@ -169,8 +177,11 @@ pub struct CastPass;
/// **Known problems:** None
///
/// **Example:** `let x = u64::MAX; x as f64`
declare_lint!(pub CAST_PRECISION_LOSS, Allow,
"casts that cause loss of precision, e.g `x as f32` where `x: u64`");
declare_lint! {
pub CAST_PRECISION_LOSS, Allow,
"casts that cause loss of precision, e.g `x as f32` where `x: u64`"
}
/// **What it does:** This lint checks for casts from a signed to an unsigned numerical type. In this case, negative values wrap around to large positive values, which can be quite surprising in practice. However, as the cast works as defined, this lint is `Allow` by default.
///
/// **Why is this bad?** Possibly surprising results. You can activate this lint as a one-time check to see where numerical wrapping can arise.
@ -178,8 +189,11 @@ declare_lint!(pub CAST_PRECISION_LOSS, Allow,
/// **Known problems:** None
///
/// **Example:** `let y : i8 = -1; y as u64` will return 18446744073709551615
declare_lint!(pub CAST_SIGN_LOSS, Allow,
"casts from signed types to unsigned types, e.g `x as u32` where `x: i32`");
declare_lint! {
pub CAST_SIGN_LOSS, Allow,
"casts from signed types to unsigned types, e.g `x as u32` where `x: i32`"
}
/// **What it does:** This lint checks for on casts between numerical types that may truncate large values. This is expected behavior, so the cast is `Allow` by default.
///
/// **Why is this bad?** In some problem domains, it is good practice to avoid truncation. This lint can be activated to help assess where additional checks could be beneficial.
@ -187,8 +201,11 @@ declare_lint!(pub CAST_SIGN_LOSS, Allow,
/// **Known problems:** None
///
/// **Example:** `fn as_u8(x: u64) -> u8 { x as u8 }`
declare_lint!(pub 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`");
declare_lint! {
pub 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`"
}
/// **What it does:** This lint checks for casts from an unsigned type to a signed type of the same size. Performing such a cast is a 'no-op' for the compiler, i.e. nothing is changed at the bit level, and the binary representation of the value is reinterpreted. This can cause wrapping if the value is too big for the target signed type. However, the cast works as defined, so this lint is `Allow` by default.
///
/// **Why is this bad?** While such a cast is not bad in itself, the results can be surprising when this is not the intended behavior, as demonstrated by the example below.
@ -196,8 +213,10 @@ declare_lint!(pub CAST_POSSIBLE_TRUNCATION, Allow,
/// **Known problems:** None
///
/// **Example:** `u32::MAX as i32` will yield a value of `-1`.
declare_lint!(pub CAST_POSSIBLE_WRAP, Allow,
"casts that may cause wrapping around the value, e.g `x as i32` where `x: u32` and `x > i32::MAX`");
declare_lint! {
pub CAST_POSSIBLE_WRAP, Allow,
"casts that may cause wrapping around the value, e.g `x as i32` where `x: u32` and `x > i32::MAX`"
}
/// Returns the size in bits of an integral type.
/// Will return 0 if the type is not an int or uint variant
@ -386,15 +405,17 @@ impl LateLintPass for CastPass {
}
}
/// **What it does:** This lint checks for types used in structs, parameters and `let` declarations above a certain complexity threshold. It is `Warn` by default.
/// **What it does:** This lint checks for types used in structs, parameters and `let` declarations above a certain complexity threshold.
///
/// **Why is this bad?** Too complex types make the code less readable. Consider using a `type` definition to simplify them.
///
/// **Known problems:** None
///
/// **Example:** `struct Foo { inner: Rc<Vec<Vec<Box<(u32, u32, u32, u32)>>>> }`
declare_lint!(pub TYPE_COMPLEXITY, Warn,
"usage of very complex types; recommends factoring out parts into `type` definitions");
declare_lint! {
pub TYPE_COMPLEXITY, Warn,
"usage of very complex types; recommends factoring out parts into `type` definitions"
}
#[allow(missing_copy_implementations)]
pub struct TypeComplexityPass;
@ -518,15 +539,17 @@ impl<'v> Visitor<'v> for TypeComplexityVisitor {
}
}
/// **What it does:** This lint points out expressions where a character literal is casted to u8 and suggests using a byte literal instead.
/// **What it does:** This lint points out expressions where a character literal is casted to `u8` and suggests using a byte literal instead.
///
/// **Why is this bad?** In general, casting values to smaller types is error-prone and should be avoided where possible. In the particular case of converting a character literal to u8, it is easy to avoid by just using a byte literal instead. As an added bonus, `b'a'` is even slightly shorter than `'a' as u8`.
///
/// **Known problems:** None
///
/// **Example:** `'x' as u8`
declare_lint!(pub CHAR_LIT_AS_U8, Warn,
"Casting a character literal to u8");
declare_lint! {
pub CHAR_LIT_AS_U8, Warn,
"Casting a character literal to u8"
}
pub struct CharLitAsU8;
@ -565,8 +588,10 @@ impl LateLintPass for CharLitAsU8 {
/// **Known problems:** None
///
/// **Example:** `vec.len() <= 0`
declare_lint!(pub ABSURD_UNSIGNED_COMPARISONS, Warn,
"testing whether an unsigned integer is non-positive");
declare_lint! {
pub ABSURD_UNSIGNED_COMPARISONS, Warn,
"testing whether an unsigned integer is non-positive"
}
pub struct AbsurdUnsignedComparisons;

View file

@ -8,35 +8,43 @@ use unicode_normalization::UnicodeNormalization;
use utils::{snippet, span_help_and_lint};
/// **What it does:** This lint checks for the unicode zero-width space in the code. It is `Warn` by default.
/// **What it does:** This lint checks for the unicode zero-width space in the code.
///
/// **Why is this bad?** Having an invisible character in the code makes for all sorts 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 somewhere in this text.
declare_lint!{ pub ZERO_WIDTH_SPACE, Deny,
"using a zero-width space in a string literal, which is confusing" }
/// **What it does:** This lint checks for non-ascii characters in string literals. It is `Allow` by default.
declare_lint! {
pub ZERO_WIDTH_SPACE, Deny,
"using a zero-width space in a string literal, which is confusing"
}
/// **What it does:** This lint checks for non-ascii characters in string literals.
///
/// **Why is this bad?** Yeah, we know, the 90's called and wanted their charset back. Even so, there still are editors and other programs out there that don't work well with unicode. So if the code is meant to be used internationally, on multiple operating systems, or has other portability requirements, activating this lint could be useful.
///
/// **Known problems:** None
///
/// **Example:** `let x = "Hä?"`
declare_lint!{ pub NON_ASCII_LITERAL, Allow,
"using any literal non-ASCII chars in a string literal; suggests \
using the \\u escape instead" }
/// **What it does:** This lint checks for string literals that contain unicode in a form that is not equal to its [NFC-recomposition](http://www.unicode.org/reports/tr15/#Norm_Forms). This lint is `Allow` by default.
declare_lint! {
pub NON_ASCII_LITERAL, Allow,
"using any literal non-ASCII chars in a string literal; suggests \
using the \\u escape instead"
}
/// **What it does:** This lint checks for string literals that contain unicode in a form that is not equal to its [NFC-recomposition](http://www.unicode.org/reports/tr15/#Norm_Forms).
///
/// **Why is this bad?** If such a string is compared to another, the results may be surprising.
///
/// **Known problems** None
///
/// **Example:** You may not see it, but "à" and "à" aren't the same string. The former when escaped is actually "a\u{300}" while the latter is "\u{e0}".
declare_lint!{ pub UNICODE_NOT_NFC, Allow,
"using a unicode literal not in NFC normal form (see \
http://www.unicode.org/reports/tr15/ for further information)" }
declare_lint! {
pub UNICODE_NOT_NFC, Allow,
"using a unicode literal not in NFC normal form (see \
http://www.unicode.org/reports/tr15/ for further information)"
}
#[derive(Copy, Clone)]

View file

@ -7,7 +7,6 @@ use utils::{BOX_NEW_PATH, VEC_FROM_ELEM_PATH};
use utils::{is_expn_of, match_path, snippet, span_lint_and_then};
/// **What it does:** This lint warns about using `&vec![..]` when using `&[..]` would be possible.
/// It is `Warn` by default.
///
/// **Why is this bad?** This is less efficient.
///

View file

@ -4,20 +4,23 @@ use rustc_front::hir::*;
use utils::span_help_and_lint;
use consts::{Constant, constant_simple, FloatWidth};
/// ZeroDivZeroPass is a pass that checks for a binary expression that consists
/// of 0.0/0.0, which is always NaN. It is more clear to replace instances of
/// 0.0/0.0 with std::f32::NaN or std::f64::NaN, depending on the precision.
/// `ZeroDivZeroPass` is a pass that checks for a binary expression that consists
/// `of 0.0/0.0`, which is always NaN. It is more clear to replace instances of
/// `0.0/0.0` with `std::f32::NaN` or `std::f64::NaN`, depending on the precision.
pub struct ZeroDivZeroPass;
/// **What it does:** This lint checks for `0.0 / 0.0`. It is `Warn` by default.
/// **What it does:** This lint checks for `0.0 / 0.0`.
///
/// **Why is this bad?** It's less readable than `std::f32::NAN` or `std::f64::NAN`
///
/// **Known problems:** None
///
/// **Example** `0.0f32 / 0.0`
declare_lint!(pub ZERO_DIVIDED_BY_ZERO, Warn,
"usage of `0.0 / 0.0` to obtain NaN instead of std::f32::NaN or std::f64::NaN");
declare_lint! {
pub ZERO_DIVIDED_BY_ZERO,
Warn,
"usage of `0.0 / 0.0` to obtain NaN instead of std::f32::NaN or std::f64::NaN"
}
impl LintPass for ZeroDivZeroPass {
fn get_lints(&self) -> LintArray {

View file

@ -8,6 +8,9 @@ import re
import sys
level_re = re.compile(r'''(Forbid|Deny|Warn|Allow)''')
def parse_path(p="src"):
d = {}
for f in os.listdir(p):
@ -38,9 +41,20 @@ def parse_file(d, f):
if not comment:
l = line.strip()
m = re.search(r"pub\s+([A-Z_]+)", l)
if m:
print("found %s in %s" % (m.group(1).lower(), f))
d[m.group(1).lower()] = last_comment
name = m.group(1).lower()
while True:
m = re.search(level_re, line)
if m:
level = m.group(0)
break
line = next(rs)
print("found %s with level %s in %s" % (name, level, f))
d[name] = (level, last_comment)
last_comment = []
comment = True
if "}" in l:
@ -51,7 +65,6 @@ PREFIX = """Welcome to the rust-clippy wiki!
Here we aim to collect further explanations on the lints clippy provides. So \
without further ado:
"""
WARNING = """
@ -61,7 +74,16 @@ Clippy works as a *plugin* to the compiler, which means using an unstable \
internal API. We have gotten quite good at keeping pace with the API \
evolution, but the consequence is that clippy absolutely needs to be compiled \
with the version of `rustc` it will run on, otherwise you will get strange \
errors of missing symbols."""
errors of missing symbols.
"""
template = """# `%s`
**Default level:** %s
%s"""
def write_wiki_page(d, f):
@ -69,11 +91,16 @@ def write_wiki_page(d, f):
keys.sort()
with open(f, "w") as w:
w.write(PREFIX)
for k in keys:
w.write("[`%s`](#%s)\n" % (k, k))
for level in ('Deny', 'Warn', 'Allow'):
w.write("\n**Those lints are %s by default**:\n\n" % level)
for k in keys:
if d[k][0] == level:
w.write("[`%s`](#%s)\n" % (k, k))
w.write(WARNING)
for k in keys:
w.write("\n# `%s`\n\n%s" % (k, "".join(d[k])))
w.write(template % (k, d[k][0], "".join(d[k][1])))
def check_wiki_page(d, f):