1
Fork 0

Various cosmetic improvements.

This commit is contained in:
Alexander Regueiro 2019-01-31 01:15:29 +00:00
parent 016d92d6ed
commit d43966a176
73 changed files with 510 additions and 470 deletions

View file

@ -191,7 +191,7 @@ pub struct FileChange {
pub new_lines: String, pub new_lines: String,
} }
/// Replace a region in a file delimited by two lines matching regexes. /// Replaces a region in a file delimited by two lines matching regexes.
/// ///
/// `path` is the relative path to the file on which you want to perform the replacement. /// `path` is the relative path to the file on which you want to perform the replacement.
/// ///
@ -225,7 +225,7 @@ where
file_change file_change
} }
/// Replace a region in a text delimited by two lines matching regexes. /// Replaces a region in a text delimited by two lines matching regexes.
/// ///
/// * `text` is the input text on which you want to perform the replacement /// * `text` is the input text on which you want to perform the replacement
/// * `start` is a `&str` that describes the delimiter line before the region you want to replace. /// * `start` is a `&str` that describes the delimiter line before the region you want to replace.

View file

@ -104,7 +104,7 @@ fn check_known_consts(cx: &LateContext<'_, '_>, e: &Expr, s: symbol::Symbol, mod
} }
} }
/// Returns false if the number of significant figures in `value` are /// Returns `false` if the number of significant figures in `value` are
/// less than `min_digits`; otherwise, returns true if `value` is equal /// less than `min_digits`; otherwise, returns true if `value` is equal
/// to `constant`, rounded to the number of digits present in `value`. /// to `constant`, rounded to the number of digits present in `value`.
fn is_approx_const(constant: f64, value: &str, min_digits: usize) -> bool { fn is_approx_const(constant: f64, value: &str, min_digits: usize) -> bool {

View file

@ -1,13 +1,14 @@
use if_chain::if_chain;
use rustc::hir::{Expr, ExprKind};
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::{declare_tool_lint, lint_array};
use crate::consts::{constant, Constant}; use crate::consts::{constant, Constant};
use crate::rustc::hir::{Expr, ExprKind};
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
use crate::syntax::ast::LitKind; use crate::syntax::ast::LitKind;
use crate::utils::{in_macro, is_direct_expn_of, span_help_and_lint}; use crate::utils::{in_macro, is_direct_expn_of, span_help_and_lint};
use if_chain::if_chain;
declare_clippy_lint! { declare_clippy_lint! {
/// **What it does:** Check to call assert!(true/false) /// **What it does:** Checks for `assert!(true)` and `assert!(false)` calls.
/// ///
/// **Why is this bad?** Will be optimized out by the compiler or should probably be replaced by a /// **Why is this bad?** Will be optimized out by the compiler or should probably be replaced by a
/// panic!() or unreachable!() /// panic!() or unreachable!()
@ -15,17 +16,18 @@ declare_clippy_lint! {
/// **Known problems:** None /// **Known problems:** None
/// ///
/// **Example:** /// **Example:**
/// ```no_run /// ```rust
/// assert!(false); /// assert!(false)
/// // or /// // or
/// assert!(true); /// assert!(true)
/// // or /// // or
/// const B: bool = false; /// const B: bool = false;
/// assert!(B); /// assert!(B)
/// ``` /// ```
pub ASSERTIONS_ON_CONSTANTS, pub ASSERTIONS_ON_CONSTANTS,
style, style,
"assert!(true/false) will be optimized out by the compiler/should probably be replaced by a panic!() or unreachable!()" "`assert!(true)` / `assert!(false)` will be optimized out by the compiler, \
and should probably be replaced by a `panic!()` or `unreachable!()`"
} }
pub struct AssertionsOnConstants; pub struct AssertionsOnConstants;

View file

@ -1,13 +1,15 @@
use crate::utils::{
get_trait_def_id, implements_trait, snippet_opt, span_lint_and_then, trait_ref_of_method, SpanlessEq,
};
use crate::utils::{higher, sugg};
use if_chain::if_chain; use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc::hir; use rustc::hir;
use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::{declare_tool_lint, lint_array}; use rustc::{declare_tool_lint, lint_array};
use rustc_errors::Applicability;
use crate::utils::{
get_trait_def_id, implements_trait, snippet_opt, span_lint_and_then, trait_ref_of_method,
SpanlessEq,
};
use crate::utils::{higher, sugg};
declare_clippy_lint! { declare_clippy_lint! {
/// **What it does:** Checks for `a = a op b` or `a = b commutative_op a` /// **What it does:** Checks for `a = a op b` or `a = b commutative_op a`
@ -19,7 +21,7 @@ declare_clippy_lint! {
/// implementations that differ from the regular `Op` impl. /// implementations that differ from the regular `Op` impl.
/// ///
/// **Example:** /// **Example:**
/// ```ignore /// ```rust
/// let mut a = 5; /// let mut a = 5;
/// ... /// ...
/// a = a + b; /// a = a + b;
@ -36,12 +38,12 @@ declare_clippy_lint! {
/// op= b`. /// op= b`.
/// ///
/// **Known problems:** Clippy cannot know for sure if `a op= a op b` should have /// **Known problems:** Clippy cannot know for sure if `a op= a op b` should have
/// been `a = a op a op b` or `a = a op b`/`a op= b`. Therefore it suggests both. /// been `a = a op a op b` or `a = a op b`/`a op= b`. Therefore, it suggests both.
/// If `a op= a op b` is really the correct behaviour it should be /// If `a op= a op b` is really the correct behaviour it should be
/// written as `a = a op a op b` as it's less confusing. /// written as `a = a op a op b` as it's less confusing.
/// ///
/// **Example:** /// **Example:**
/// ```ignore /// ```rust
/// let mut a = 5; /// let mut a = 5;
/// ... /// ...
/// a += a + b; /// a += a + b;

View file

@ -70,7 +70,7 @@ declare_clippy_lint! {
/// ``` /// ```
pub INEFFECTIVE_BIT_MASK, pub INEFFECTIVE_BIT_MASK,
correctness, correctness,
"expressions where a bit mask will be rendered useless by a comparison, e.g. `(x | 1) > 2`" "expressions where a bit mask will be rendered useless by a comparison, e.g., `(x | 1) > 2`"
} }
declare_clippy_lint! { declare_clippy_lint! {

View file

@ -20,7 +20,7 @@ declare_clippy_lint! {
/// ``` /// ```
pub BLOCK_IN_IF_CONDITION_EXPR, pub BLOCK_IN_IF_CONDITION_EXPR,
style, style,
"braces that can be eliminated in conditions, e.g. `if { true } ...`" "braces that can be eliminated in conditions, e.g., `if { true } ...`"
} }
declare_clippy_lint! { declare_clippy_lint! {
@ -39,7 +39,7 @@ declare_clippy_lint! {
/// ``` /// ```
pub BLOCK_IN_IF_CONDITION_STMT, pub BLOCK_IN_IF_CONDITION_STMT,
style, style,
"complex blocks in conditions, e.g. `if { let x = true; x } ...`" "complex blocks in conditions, e.g., `if { let x = true; x } ...`"
} }
#[derive(Copy, Clone)] #[derive(Copy, Clone)]

View file

@ -68,7 +68,7 @@ declare_clippy_lint! {
/// ``` /// ```
pub COLLAPSIBLE_IF, pub COLLAPSIBLE_IF,
style, style,
"`if`s that can be collapsed (e.g. `if x { if y { ... } }` and `else { if x { ... } }`)" "`if`s that can be collapsed (e.g., `if x { if y { ... } }` and `else { if x { ... } }`)"
} }
#[derive(Copy, Clone)] #[derive(Copy, Clone)]

View file

@ -21,27 +21,27 @@ use syntax_pos::symbol::Symbol;
/// A `LitKind`-like enum to fold constant `Expr`s into. /// A `LitKind`-like enum to fold constant `Expr`s into.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum Constant { pub enum Constant {
/// a String "abc" /// A `String` (e.g., "abc").
Str(String), Str(String),
/// a Binary String b"abc" /// A binary string (e.g., `b"abc"`).
Binary(Lrc<Vec<u8>>), Binary(Lrc<Vec<u8>>),
/// a single char 'a' /// A single `char` (e.g., `'a'`).
Char(char), Char(char),
/// an integer's bit representation /// An integer's bit representation.
Int(u128), Int(u128),
/// an f32 /// An `f32`.
F32(f32), F32(f32),
/// an f64 /// An `f64`.
F64(f64), F64(f64),
/// true or false /// `true` or `false`.
Bool(bool), Bool(bool),
/// an array of constants /// An array of constants.
Vec(Vec<Constant>), Vec(Vec<Constant>),
/// also an array, but with only one constant, repeated N times /// Also an array, but with only one constant, repeated N times.
Repeat(Box<Constant>, u64), Repeat(Box<Constant>, u64),
/// a tuple of constants /// A tuple of constants.
Tuple(Vec<Constant>), Tuple(Vec<Constant>),
/// a literal with syntax error /// A literal with syntax error.
Err(Symbol), Err(Symbol),
} }
@ -53,15 +53,15 @@ impl PartialEq for Constant {
(&Constant::Char(l), &Constant::Char(r)) => l == r, (&Constant::Char(l), &Constant::Char(r)) => l == r,
(&Constant::Int(l), &Constant::Int(r)) => l == r, (&Constant::Int(l), &Constant::Int(r)) => l == r,
(&Constant::F64(l), &Constant::F64(r)) => { (&Constant::F64(l), &Constant::F64(r)) => {
// we want `Fw32 == FwAny` and `FwAny == Fw64`, by transitivity we must have // We want `Fw32 == FwAny` and `FwAny == Fw64`, and by transitivity we must have
// `Fw32 == Fw64` so dont compare them // `Fw32 == Fw64`, so dont compare them.
// to_bits is required to catch non-matching 0.0, -0.0, and NaNs // `to_bits` is required to catch non-matching 0.0, -0.0, and NaNs.
l.to_bits() == r.to_bits() l.to_bits() == r.to_bits()
}, },
(&Constant::F32(l), &Constant::F32(r)) => { (&Constant::F32(l), &Constant::F32(r)) => {
// we want `Fw32 == FwAny` and `FwAny == Fw64`, by transitivity we must have // We want `Fw32 == FwAny` and `FwAny == Fw64`, and by transitivity we must have
// `Fw32 == Fw64` so dont compare them // `Fw32 == Fw64`, so dont compare them.
// to_bits is required to catch non-matching 0.0, -0.0, and NaNs // `to_bits` is required to catch non-matching 0.0, -0.0, and NaNs.
f64::from(l).to_bits() == f64::from(r).to_bits() f64::from(l).to_bits() == f64::from(r).to_bits()
}, },
(&Constant::Bool(l), &Constant::Bool(r)) => l == r, (&Constant::Bool(l), &Constant::Bool(r)) => l == r,
@ -69,7 +69,8 @@ impl PartialEq for Constant {
l == r l == r
}, },
(&Constant::Repeat(ref lv, ref ls), &Constant::Repeat(ref rv, ref rs)) => ls == rs && lv == rv, (&Constant::Repeat(ref lv, ref ls), &Constant::Repeat(ref rv, ref rs)) => ls == rs && lv == rv,
_ => false, // TODO: Are there inter-type equalities? // TODO: are there inter-type equalities?
_ => false,
} }
} }
} }
@ -142,12 +143,13 @@ impl Constant {
x => x, x => x,
} }
}, },
_ => None, // TODO: Are there any useful inter-type orderings? // TODO: are there any useful inter-type orderings?
_ => None,
} }
} }
} }
/// parse a `LitKind` to a `Constant` /// Parses a `LitKind` to a `Constant`.
pub fn lit_to_constant<'tcx>(lit: &LitKind, ty: Ty<'tcx>) -> Constant { pub fn lit_to_constant<'tcx>(lit: &LitKind, ty: Ty<'tcx>) -> Constant {
use syntax::ast::*; use syntax::ast::*;

View file

@ -239,9 +239,9 @@ fn lint_match_arms(cx: &LateContext<'_, '_>, expr: &Expr) {
} }
} }
/// Return the list of condition expressions and the list of blocks in a /// Returns the list of condition expressions and the list of blocks in a
/// sequence of `if/else`. /// sequence of `if/else`.
/// Eg. would return `([a, b], [c, d, e])` for the expression /// E.g., this returns `([a, b], [c, d, e])` for the expression
/// `if a { c } else if b { d } else { e }`. /// `if a { c } else if b { d } else { e }`.
fn if_sequence(mut expr: &Expr) -> (SmallVec<[&Expr; 1]>, SmallVec<[&Block; 1]>) { fn if_sequence(mut expr: &Expr) -> (SmallVec<[&Expr; 1]>, SmallVec<[&Block; 1]>) {
let mut conds = SmallVec::new(); let mut conds = SmallVec::new();
@ -272,7 +272,7 @@ fn if_sequence(mut expr: &Expr) -> (SmallVec<[&Expr; 1]>, SmallVec<[&Block; 1]>)
(conds, blocks) (conds, blocks)
} }
/// Return the list of bindings in a pattern. /// Returns the list of bindings in a pattern.
fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> FxHashMap<LocalInternedString, Ty<'tcx>> { fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> FxHashMap<LocalInternedString, Ty<'tcx>> {
fn bindings_impl<'a, 'tcx>( fn bindings_impl<'a, 'tcx>(
cx: &LateContext<'a, 'tcx>, cx: &LateContext<'a, 'tcx>,

View file

@ -90,7 +90,7 @@ declare_deprecated_lint! {
/// counterparts, so this lint may suggest a change in behavior or the code may not compile. /// counterparts, so this lint may suggest a change in behavior or the code may not compile.
declare_deprecated_lint! { declare_deprecated_lint! {
pub ASSIGN_OPS, pub ASSIGN_OPS,
"using compound assignment operators (e.g. `+=`) is harmless" "using compound assignment operators (e.g., `+=`) is harmless"
} }
/// **What it does:** Nothing. This lint has been deprecated. /// **What it does:** Nothing. This lint has been deprecated.

View file

@ -257,8 +257,8 @@ fn check_text(cx: &EarlyContext<'_>, valid_idents: &FxHashSet<String>, text: &st
} }
fn check_word(cx: &EarlyContext<'_>, word: &str, span: Span) { fn check_word(cx: &EarlyContext<'_>, word: &str, span: Span) {
/// Checks if a string is camel-case, ie. contains at least two uppercase /// Checks if a string is camel-case, i.e., contains at least two uppercase
/// letter (`Clippy` is /// letters (`Clippy` is
/// ok) and one lower-case letter (`NASA` is ok). Plural are also excluded /// ok) and one lower-case letter (`NASA` is ok). Plural are also excluded
/// (`IDs` is ok). /// (`IDs` is ok).
fn is_camel_case(s: &str) -> bool { fn is_camel_case(s: &str) -> bool {

View file

@ -1,4 +1,4 @@
//! lint on if expressions with an else if, but without a final else branch //! Lint on if expressions with an else if, but without a final else branch.
use rustc::lint::{in_external_macro, EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass}; use rustc::lint::{in_external_macro, EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass};
use rustc::{declare_tool_lint, lint_array}; use rustc::{declare_tool_lint, lint_array};
@ -10,7 +10,7 @@ declare_clippy_lint! {
/// **What it does:** Checks for usage of if expressions with an `else if` branch, /// **What it does:** Checks for usage of if expressions with an `else if` branch,
/// but without a final `else` branch. /// but without a final `else` branch.
/// ///
/// **Why is this bad?** Some coding guidelines require this (e.g. MISRA-C:2004 Rule 14.10). /// **Why is this bad?** Some coding guidelines require this (e.g., MISRA-C:2004 Rule 14.10).
/// ///
/// **Known problems:** None. /// **Known problems:** None.
/// ///
@ -31,7 +31,7 @@ declare_clippy_lint! {
/// } else if x.is_negative() { /// } else if x.is_negative() {
/// b(); /// b();
/// } else { /// } else {
/// // we don't care about zero /// // We don't care about zero.
/// } /// }
/// ``` /// ```
pub ELSE_IF_WITHOUT_ELSE, pub ELSE_IF_WITHOUT_ELSE,

View file

@ -24,7 +24,7 @@ declare_clippy_lint! {
/// ``` /// ```
pub EQ_OP, pub EQ_OP,
correctness, correctness,
"equal operands on both sides of a comparison or bitwise combination (e.g. `x == x`)" "equal operands on both sides of a comparison or bitwise combination (e.g., `x == x`)"
} }
declare_clippy_lint! { declare_clippy_lint! {

View file

@ -1,12 +1,13 @@
use crate::consts::{constant_simple, Constant};
use crate::utils::{in_macro, span_lint};
use rustc::hir::*; use rustc::hir::*;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::{declare_tool_lint, lint_array}; use rustc::{declare_tool_lint, lint_array};
use syntax::source_map::Span; use syntax::source_map::Span;
use crate::consts::{constant_simple, Constant};
use crate::utils::{in_macro, span_lint};
declare_clippy_lint! { declare_clippy_lint! {
/// **What it does:** Checks for erasing operations, e.g. `x * 0`. /// **What it does:** Checks for erasing operations, e.g., `x * 0`.
/// ///
/// **Why is this bad?** The whole expression can be replaced by zero. /// **Why is this bad?** The whole expression can be replaced by zero.
/// This is most likely not the intended outcome and should probably be /// This is most likely not the intended outcome and should probably be
@ -15,14 +16,14 @@ declare_clippy_lint! {
/// **Known problems:** None. /// **Known problems:** None.
/// ///
/// **Example:** /// **Example:**
/// ```ignore /// ```rust
/// 0 / x; /// 0 / x;
/// 0 * x; /// 0 * x;
/// x & 0 /// x & 0
/// ``` /// ```
pub ERASING_OP, pub ERASING_OP,
correctness, correctness,
"using erasing operations, e.g. `x * 0` or `y & 0`" "using erasing operations, e.g., `x * 0` or `y & 0`"
} }
#[derive(Copy, Clone)] #[derive(Copy, Clone)]

View file

@ -1,4 +1,3 @@
use crate::utils::span_lint;
use rustc::hir::intravisit as visit; use rustc::hir::intravisit as visit;
use rustc::hir::*; use rustc::hir::*;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
@ -10,6 +9,8 @@ use rustc::util::nodemap::HirIdSet;
use rustc::{declare_tool_lint, lint_array}; use rustc::{declare_tool_lint, lint_array};
use syntax::source_map::Span; use syntax::source_map::Span;
use crate::utils::span_lint;
pub struct Pass { pub struct Pass {
pub too_large_for_stack: u64, pub too_large_for_stack: u64,
} }
@ -67,7 +68,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
_: Span, _: Span,
hir_id: HirId, hir_id: HirId,
) { ) {
// If the method is an impl for a trait, don't warn // If the method is an impl for a trait, don't warn.
let parent_id = cx.tcx.hir().get_parent_item(hir_id); let parent_id = cx.tcx.hir().get_parent_item(hir_id);
let parent_node = cx.tcx.hir().find_by_hir_id(parent_id); let parent_node = cx.tcx.hir().find_by_hir_id(parent_id);
@ -102,7 +103,7 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> {
fn consume(&mut self, _: HirId, _: Span, cmt: &cmt_<'tcx>, mode: ConsumeMode) { fn consume(&mut self, _: HirId, _: Span, cmt: &cmt_<'tcx>, mode: ConsumeMode) {
if let Categorization::Local(lid) = cmt.cat { if let Categorization::Local(lid) = cmt.cat {
if let Move(DirectRefMove) = mode { if let Move(DirectRefMove) = mode {
// moved out or in. clearly can't be localized // Moved out or in. Clearly can't be localized.
self.set.remove(&lid); self.set.remove(&lid);
} }
} }
@ -158,20 +159,20 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> {
) { ) {
if let Categorization::Local(lid) = cmt.cat { if let Categorization::Local(lid) = cmt.cat {
match loan_cause { match loan_cause {
// x.foo() // `x.foo()`
// Used without autodereffing (i.e. x.clone()) // Used without autoderef-ing (i.e., `x.clone()`).
LoanCause::AutoRef | LoanCause::AutoRef |
// &x // `&x`
// foo(&x) where no extra autoreffing is happening // `foo(&x)` where no extra autoref-ing is happening.
LoanCause::AddrOf | LoanCause::AddrOf |
// `match x` can move // `match x` can move.
LoanCause::MatchDiscriminant => { LoanCause::MatchDiscriminant => {
self.set.remove(&lid); self.set.remove(&lid);
} }
// do nothing for matches, etc. These can't escape // Do nothing for matches, etc. These can't escape.
_ => {} _ => {}
} }
} }
@ -182,8 +183,7 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> {
impl<'a, 'tcx> EscapeDelegate<'a, 'tcx> { impl<'a, 'tcx> EscapeDelegate<'a, 'tcx> {
fn is_large_box(&self, ty: Ty<'tcx>) -> bool { fn is_large_box(&self, ty: Ty<'tcx>) -> bool {
// Large types need to be boxed to avoid stack // Large types need to be boxed to avoid stack overflows.
// overflows.
if ty.is_box() { if ty.is_box() {
self.cx.layout_of(ty.boxed_ty()).ok().map_or(0, |l| l.size.bytes()) > self.too_large_for_stack self.cx.layout_of(ty.boxed_ty()).ok().map_or(0, |l| l.size.bytes()) > self.too_large_for_stack
} else { } else {

View file

@ -1,4 +1,3 @@
use crate::utils::{is_adjusted, iter_input_pats, snippet_opt, span_lint_and_then, type_is_unsafe_function};
use if_chain::if_chain; use if_chain::if_chain;
use rustc::hir::*; use rustc::hir::*;
use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass}; use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass};
@ -6,6 +5,8 @@ use rustc::ty;
use rustc::{declare_tool_lint, lint_array}; use rustc::{declare_tool_lint, lint_array};
use rustc_errors::Applicability; use rustc_errors::Applicability;
use crate::utils::{is_adjusted, iter_input_pats, snippet_opt, span_lint_and_then, type_is_unsafe_function};
pub struct EtaPass; pub struct EtaPass;
declare_clippy_lint! { declare_clippy_lint! {
@ -19,18 +20,17 @@ declare_clippy_lint! {
/// **Known problems:** If creating the closure inside the closure has a side- /// **Known problems:** If creating the closure inside the closure has a side-
/// effect then moving the closure creation out will change when that side- /// effect then moving the closure creation out will change when that side-
/// effect runs. /// effect runs.
/// See https://github.com/rust-lang/rust-clippy/issues/1439 for more /// See rust-lang/rust-clippy#1439 for more details.
/// details.
/// ///
/// **Example:** /// **Example:**
/// ```ignore /// ```rust
/// xs.map(|x| foo(x)) /// xs.map(|x| foo(x))
/// ``` /// ```
/// where `foo(_)` is a plain function that takes the exact argument type of /// where `foo(_)` is a plain function that takes the exact argument type of
/// `x`. /// `x`.
pub REDUNDANT_CLOSURE, pub REDUNDANT_CLOSURE,
style, style,
"redundant closures, i.e. `|a| foo(a)` (which can be written as just `foo`)" "redundant closures, i.e., `|a| foo(a)` (which can be written as just `foo`)"
} }
impl LintPass for EtaPass { impl LintPass for EtaPass {

View file

@ -286,7 +286,7 @@ fn check_stmt<'a, 'tcx>(vis: &mut ReadVisitor<'a, 'tcx>, stmt: &'tcx Stmt) -> St
/// A visitor that looks for reads from a variable. /// A visitor that looks for reads from a variable.
struct ReadVisitor<'a, 'tcx: 'a> { struct ReadVisitor<'a, 'tcx: 'a> {
cx: &'a LateContext<'a, 'tcx>, cx: &'a LateContext<'a, 'tcx>,
/// The id of the variable we're looking for. /// The ID of the variable we're looking for.
var: ast::NodeId, var: ast::NodeId,
/// The expressions where the write to the variable occurred (for reporting /// The expressions where the write to the variable occurred (for reporting
/// in the lint). /// in the lint).
@ -351,7 +351,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ReadVisitor<'a, 'tcx> {
} }
} }
/// Returns true if `expr` is the LHS of an assignment, like `expr = ...`. /// Returns `true` if `expr` is the LHS of an assignment, like `expr = ...`.
fn is_in_assignment_position(cx: &LateContext<'_, '_>, expr: &Expr) -> bool { fn is_in_assignment_position(cx: &LateContext<'_, '_>, expr: &Expr) -> bool {
if let Some(parent) = get_parent_expr(cx, expr) { if let Some(parent) = get_parent_expr(cx, expr) {
if let ExprKind::Assign(ref lhs, _) = parent.node { if let ExprKind::Assign(ref lhs, _) = parent.node {

View file

@ -1,13 +1,14 @@
use crate::consts::{constant_simple, Constant};
use crate::utils::{clip, in_macro, snippet, span_lint, unsext};
use rustc::hir::*; use rustc::hir::*;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::ty; use rustc::ty;
use rustc::{declare_tool_lint, lint_array}; use rustc::{declare_tool_lint, lint_array};
use syntax::source_map::Span; use syntax::source_map::Span;
use crate::consts::{constant_simple, Constant};
use crate::utils::{clip, in_macro, snippet, span_lint, unsext};
declare_clippy_lint! { declare_clippy_lint! {
/// **What it does:** Checks for identity operations, e.g. `x + 0`. /// **What it does:** Checks for identity operations, e.g., `x + 0`.
/// ///
/// **Why is this bad?** This code can be removed without changing the /// **Why is this bad?** This code can be removed without changing the
/// meaning. So it just obscures what's going on. Delete it mercilessly. /// meaning. So it just obscures what's going on. Delete it mercilessly.
@ -20,7 +21,7 @@ declare_clippy_lint! {
/// ``` /// ```
pub IDENTITY_OP, pub IDENTITY_OP,
complexity, complexity,
"using identity operations, e.g. `x + 0` or `y / 1`" "using identity operations, e.g., `x + 0` or `y / 1`"
} }
#[derive(Copy, Clone)] #[derive(Copy, Clone)]

View file

@ -103,7 +103,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IndexingSlicing {
if let ExprKind::Index(ref array, ref index) = &expr.node { if let ExprKind::Index(ref array, ref index) = &expr.node {
let ty = cx.tables.expr_ty(array); let ty = cx.tables.expr_ty(array);
if let Some(range) = higher::range(cx, index) { if let Some(range) = higher::range(cx, index) {
// Ranged indexes, i.e. &x[n..m], &x[n..], &x[..n] and &x[..] // Ranged indexes, i.e., &x[n..m], &x[n..], &x[..n] and &x[..]
if let ty::Array(_, s) = ty.sty { if let ty::Array(_, s) = ty.sty {
let size: u128 = s.assert_usize(cx.tcx).unwrap().into(); let size: u128 = s.assert_usize(cx.tcx).unwrap().into();
@ -149,7 +149,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IndexingSlicing {
utils::span_help_and_lint(cx, INDEXING_SLICING, expr.span, "slicing may panic.", help_msg); utils::span_help_and_lint(cx, INDEXING_SLICING, expr.span, "slicing may panic.", help_msg);
} else { } else {
// Catchall non-range index, i.e. [n] or [n << m] // Catchall non-range index, i.e., [n] or [n << m]
if let ty::Array(..) = ty.sty { if let ty::Array(..) = ty.sty {
// Index is a constant uint. // Index is a constant uint.
if let Some(..) = constant(cx, cx.tables, index) { if let Some(..) = constant(cx, cx.tables, index) {

View file

@ -1,13 +1,14 @@
use crate::utils::{get_trait_def_id, higher, implements_trait, match_qpath, match_type, paths, span_lint};
use rustc::hir::*; use rustc::hir::*;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::{declare_tool_lint, lint_array}; use rustc::{declare_tool_lint, lint_array};
use crate::utils::{get_trait_def_id, higher, implements_trait, match_qpath, match_type, paths, span_lint};
declare_clippy_lint! { declare_clippy_lint! {
/// **What it does:** Checks for iteration that is guaranteed to be infinite. /// **What it does:** Checks for iteration that is guaranteed to be infinite.
/// ///
/// **Why is this bad?** While there may be places where this is acceptable /// **Why is this bad?** While there may be places where this is acceptable
/// (e.g. in event streams), in most cases this is simply an error. /// (e.g., in event streams), in most cases this is simply an error.
/// ///
/// **Known problems:** None. /// **Known problems:** None.
/// ///
@ -26,7 +27,7 @@ declare_clippy_lint! {
/// **What it does:** Checks for iteration that may be infinite. /// **What it does:** Checks for iteration that may be infinite.
/// ///
/// **Why is this bad?** While there may be places where this is acceptable /// **Why is this bad?** While there may be places where this is acceptable
/// (e.g. in event streams), in most cases this is simply an error. /// (e.g., in event streams), in most cases this is simply an error.
/// ///
/// **Known problems:** The code may have a condition to stop iteration, but /// **Known problems:** The code may have a condition to stop iteration, but
/// this lint is not clever enough to analyze it. /// this lint is not clever enough to analyze it.
@ -122,8 +123,8 @@ use self::Heuristic::{All, Always, Any, First};
/// a slice of (method name, number of args, heuristic, bounds) tuples /// a slice of (method name, number of args, heuristic, bounds) tuples
/// that will be used to determine whether the method in question /// that will be used to determine whether the method in question
/// returns an infinite or possibly infinite iterator. The finiteness /// returns an infinite or possibly infinite iterator. The finiteness
/// is an upper bound, e.g. some methods can return a possibly /// is an upper bound, e.g., some methods can return a possibly
/// infinite iterator at worst, e.g. `take_while`. /// infinite iterator at worst, e.g., `take_while`.
static HEURISTICS: &[(&str, usize, Heuristic, Finiteness)] = &[ static HEURISTICS: &[(&str, usize, Heuristic, Finiteness)] = &[
("zip", 2, All, Infinite), ("zip", 2, All, Infinite),
("chain", 2, Any, Infinite), ("chain", 2, Any, Infinite),

View file

@ -274,9 +274,9 @@ fn check_len(
} }
} }
/// Check if this type has an `is_empty` method. /// Checks if this type has an `is_empty` method.
fn has_is_empty(cx: &LateContext<'_, '_>, expr: &Expr) -> bool { fn has_is_empty(cx: &LateContext<'_, '_>, expr: &Expr) -> bool {
/// Get an `AssociatedItem` and return true if it matches `is_empty(self)`. /// Gets an `AssociatedItem` and return true if it matches `is_empty(self)`.
fn is_is_empty(cx: &LateContext<'_, '_>, item: &ty::AssociatedItem) -> bool { fn is_is_empty(cx: &LateContext<'_, '_>, item: &ty::AssociatedItem) -> bool {
if let ty::AssociatedKind::Method = item.kind { if let ty::AssociatedKind::Method = item.kind {
if item.ident.name == "is_empty" { if item.ident.name == "is_empty" {
@ -291,7 +291,7 @@ fn has_is_empty(cx: &LateContext<'_, '_>, expr: &Expr) -> bool {
} }
} }
/// Check the inherent impl's items for an `is_empty(self)` method. /// Checks the inherent impl's items for an `is_empty(self)` method.
fn has_is_empty_impl(cx: &LateContext<'_, '_>, id: DefId) -> bool { fn has_is_empty_impl(cx: &LateContext<'_, '_>, id: DefId) -> bool {
cx.tcx cx.tcx
.inherent_impls(id) .inherent_impls(id)

View file

@ -11,7 +11,7 @@
#![feature(crate_visibility_modifier)] #![feature(crate_visibility_modifier)]
// FIXME: switch to something more ergonomic here, once available. // FIXME: switch to something more ergonomic here, once available.
// (currently there is no way to opt into sysroot crates w/o `extern crate`) // (Currently there is no way to opt into sysroot crates without `extern crate`.)
#[allow(unused_extern_crates)] #[allow(unused_extern_crates)]
extern crate fmt_macros; extern crate fmt_macros;
#[allow(unused_extern_crates)] #[allow(unused_extern_crates)]
@ -407,7 +407,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
); );
store.register_removed( store.register_removed(
"assign_ops", "assign_ops",
"using compound assignment operators (e.g. `+=`) is harmless", "using compound assignment operators (e.g., `+=`) is harmless",
); );
store.register_removed( store.register_removed(
"if_let_redundant_pattern_matching", "if_let_redundant_pattern_matching",

View file

@ -1,5 +1,3 @@
use crate::reexport::*;
use crate::utils::{last_path_segment, span_lint};
use matches::matches; use matches::matches;
use rustc::hir::def::Def; use rustc::hir::def::Def;
use rustc::hir::intravisit::*; use rustc::hir::intravisit::*;
@ -10,6 +8,9 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use syntax::source_map::Span; use syntax::source_map::Span;
use syntax::symbol::keywords; use syntax::symbol::keywords;
use crate::reexport::*;
use crate::utils::{last_path_segment, span_lint};
declare_clippy_lint! { declare_clippy_lint! {
/// **What it does:** Checks for lifetime annotations which can be removed by /// **What it does:** Checks for lifetime annotations which can be removed by
/// relying on lifetime elision. /// relying on lifetime elision.
@ -19,7 +20,7 @@ declare_clippy_lint! {
/// them leads to more readable code. /// them leads to more readable code.
/// ///
/// **Known problems:** Potential false negatives: we bail out if the function /// **Known problems:** Potential false negatives: we bail out if the function
/// has a `where` clause where lifetimes are mentioned. /// has a where-clause where lifetimes are mentioned.
/// ///
/// **Example:** /// **Example:**
/// ```rust /// ```rust
@ -384,7 +385,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> {
} }
} }
/// Are any lifetimes mentioned in the `where` clause? If yes, we don't try to /// Are any lifetimes mentioned in the where-clause? If yes, we don't try to
/// reason about elision. /// reason about elision.
fn has_where_lifetimes<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, where_clause: &'tcx WhereClause) -> bool { fn has_where_lifetimes<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, where_clause: &'tcx WhereClause) -> bool {
for predicate in &where_clause.predicates { for predicate in &where_clause.predicates {

View file

@ -112,7 +112,7 @@ pub(super) enum Radix {
} }
impl Radix { impl Radix {
/// Return a reasonable digit group size for this radix. /// Returns a reasonable digit group size for this radix.
crate fn suggest_grouping(&self) -> usize { crate fn suggest_grouping(&self) -> usize {
match *self { match *self {
Radix::Binary | Radix::Hexadecimal => 4, Radix::Binary | Radix::Hexadecimal => 4,

View file

@ -727,7 +727,7 @@ fn never_loop_expr(expr: &Expr, main_loop_id: HirId) -> NeverLoopResult {
ExprKind::Continue(d) => { ExprKind::Continue(d) => {
let id = d let id = d
.target_id .target_id
.expect("target id can only be missing in the presence of compilation errors"); .expect("target ID can only be missing in the presence of compilation errors");
if id == main_loop_id { if id == main_loop_id {
NeverLoopResult::MayContinueMainLoop NeverLoopResult::MayContinueMainLoop
} else { } else {
@ -953,7 +953,7 @@ fn get_indexed_assignments<'a, 'tcx>(
} }
} }
/// Check for for loops that sequentially copy items from one slice-like /// Checks for for loops that sequentially copy items from one slice-like
/// object to another. /// object to another.
fn detect_manual_memcpy<'a, 'tcx>( fn detect_manual_memcpy<'a, 'tcx>(
cx: &LateContext<'a, 'tcx>, cx: &LateContext<'a, 'tcx>,
@ -1065,7 +1065,7 @@ fn detect_manual_memcpy<'a, 'tcx>(
} }
} }
/// Check for looping over a range and then indexing a sequence with it. /// Checks for looping over a range and then indexing a sequence with it.
/// The iteratee must be a range literal. /// The iteratee must be a range literal.
#[allow(clippy::too_many_lines)] #[allow(clippy::too_many_lines)]
fn check_for_loop_range<'a, 'tcx>( fn check_for_loop_range<'a, 'tcx>(
@ -1413,7 +1413,7 @@ fn check_for_loop_arg(cx: &LateContext<'_, '_>, pat: &Pat, arg: &Expr, expr: &Ex
} }
} }
/// Check for `for` loops over `Option`s and `Results` /// Checks for `for` loops over `Option`s and `Results`
fn check_arg_type(cx: &LateContext<'_, '_>, pat: &Pat, arg: &Expr) { fn check_arg_type(cx: &LateContext<'_, '_>, pat: &Pat, arg: &Expr) {
let ty = cx.tables.expr_ty(arg); let ty = cx.tables.expr_ty(arg);
if match_type(cx, ty, &paths::OPTION) { if match_type(cx, ty, &paths::OPTION) {
@ -1507,7 +1507,7 @@ fn check_for_loop_explicit_counter<'a, 'tcx>(
} }
} }
/// Check for the `FOR_KV_MAP` lint. /// Checks for the `FOR_KV_MAP` lint.
fn check_for_loop_over_map_kv<'a, 'tcx>( fn check_for_loop_over_map_kv<'a, 'tcx>(
cx: &LateContext<'a, 'tcx>, cx: &LateContext<'a, 'tcx>,
pat: &'tcx Pat, pat: &'tcx Pat,
@ -1673,7 +1673,7 @@ fn check_for_mutation(
delegate.mutation_span() delegate.mutation_span()
} }
/// Return true if the pattern is a `PatWild` or an ident prefixed with `'_'`. /// Returns `true` if the pattern is a `PatWild` or an ident prefixed with `'_'`.
fn pat_is_wild<'tcx>(pat: &'tcx PatKind, body: &'tcx Expr) -> bool { fn pat_is_wild<'tcx>(pat: &'tcx PatKind, body: &'tcx Expr) -> bool {
match *pat { match *pat {
PatKind::Wild => true, PatKind::Wild => true,
@ -1967,7 +1967,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarUsedAfterLoopVisitor<'a, 'tcx> {
} }
} }
/// Return true if the type of expr is one that provides `IntoIterator` impls /// Returns `true` if the type of expr is one that provides `IntoIterator` impls
/// for `&T` and `&mut T`, such as `Vec`. /// for `&T` and `&mut T`, such as `Vec`.
#[rustfmt::skip] #[rustfmt::skip]
fn is_ref_iterable_type(cx: &LateContext<'_, '_>, e: &Expr) -> bool { fn is_ref_iterable_type(cx: &LateContext<'_, '_>, e: &Expr) -> bool {
@ -2022,7 +2022,7 @@ fn extract_first_expr(block: &Block) -> Option<&Expr> {
} }
} }
/// Return true if expr contains a single break expr without destination label /// Returns `true` if expr contains a single break expr without destination label
/// and /// and
/// passed expression. The expression may be within a block. /// passed expression. The expression may be within a block.
fn is_simple_break_expr(expr: &Expr) -> bool { fn is_simple_break_expr(expr: &Expr) -> bool {
@ -2102,7 +2102,7 @@ impl<'a, 'tcx> Visitor<'tcx> for IncrementVisitor<'a, 'tcx> {
} }
} }
/// Check whether a variable is initialized to zero at the start of a loop. /// Checks whether a variable is initialized to zero at the start of a loop.
struct InitializeVisitor<'a, 'tcx: 'a> { struct InitializeVisitor<'a, 'tcx: 'a> {
cx: &'a LateContext<'a, 'tcx>, // context reference cx: &'a LateContext<'a, 'tcx>, // context reference
end_expr: &'tcx Expr, // the for loop. Stop scanning here. end_expr: &'tcx Expr, // the for loop. Stop scanning here.
@ -2336,7 +2336,7 @@ fn path_name(e: &Expr) -> Option<Name> {
fn check_infinite_loop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, cond: &'tcx Expr, expr: &'tcx Expr) { fn check_infinite_loop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, cond: &'tcx Expr, expr: &'tcx Expr) {
if constant(cx, cx.tables, cond).is_some() { if constant(cx, cx.tables, cond).is_some() {
// A pure constant condition (e.g. while false) is not linted. // A pure constant condition (e.g., while false) is not linted.
return; return;
} }

View file

@ -35,7 +35,7 @@ declare_clippy_lint! {
/// ``` /// ```
pub SINGLE_MATCH, pub SINGLE_MATCH,
style, style,
"a match statement with a single nontrivial arm (i.e. where the other arm is `_ => {}`) instead of `if let`" "a match statement with a single nontrivial arm (i.e., where the other arm is `_ => {}`) instead of `if let`"
} }
declare_clippy_lint! { declare_clippy_lint! {
@ -335,7 +335,7 @@ fn check_single_match_opt_like(
let path = match arms[1].pats[0].node { let path = match arms[1].pats[0].node {
PatKind::TupleStruct(ref path, ref inner, _) => { PatKind::TupleStruct(ref path, ref inner, _) => {
// contains any non wildcard patterns? e.g. Err(err) // contains any non wildcard patterns? e.g., Err(err)
if !inner.iter().all(is_wild) { if !inner.iter().all(is_wild) {
return; return;
} }
@ -639,7 +639,7 @@ fn check_match_as_ref(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm], expr: &
} }
} }
/// Get all arms that are unbounded `PatRange`s. /// Gets all arms that are unbounded `PatRange`s.
fn all_ranges<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arms: &'tcx [Arm]) -> Vec<SpannedRange<Constant>> { fn all_ranges<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arms: &'tcx [Arm]) -> Vec<SpannedRange<Constant>> {
arms.iter() arms.iter()
.flat_map(|arm| { .flat_map(|arm| {
@ -687,7 +687,7 @@ pub struct SpannedRange<T> {
type TypedRanges = Vec<SpannedRange<u128>>; type TypedRanges = Vec<SpannedRange<u128>>;
/// Get all `Int` ranges or all `Uint` ranges. Mixed types are an error anyway /// Gets all `Int` ranges or all `Uint` ranges. Mixed types are an error anyway
/// and other types than /// and other types than
/// `Uint` and `Int` probably don't make sense. /// `Uint` and `Int` probably don't make sense.
fn type_ranges(ranges: &[SpannedRange<Constant>]) -> TypedRanges { fn type_ranges(ranges: &[SpannedRange<Constant>]) -> TypedRanges {

View file

@ -1,3 +1,22 @@
mod option_map_unwrap_or;
mod unnecessary_filter_map;
use std::borrow::Cow;
use std::fmt;
use std::iter;
use if_chain::if_chain;
use matches::matches;
use rustc::hir;
use rustc::hir::def::Def;
use rustc::lint::{in_external_macro, LateContext, LateLintPass, Lint, LintArray, LintContext, LintPass};
use rustc::ty::{self, Predicate, Ty};
use rustc::{declare_tool_lint, lint_array};
use rustc_errors::Applicability;
use syntax::ast;
use syntax::source_map::{BytePos, Span};
use syntax::symbol::LocalInternedString;
use crate::utils::paths; use crate::utils::paths;
use crate::utils::sugg; use crate::utils::sugg;
use crate::utils::{ use crate::utils::{
@ -7,23 +26,6 @@ use crate::utils::{
single_segment_path, snippet, snippet_with_applicability, snippet_with_macro_callsite, span_lint, single_segment_path, snippet, snippet_with_applicability, snippet_with_macro_callsite, span_lint,
span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth, SpanlessEq, span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth, SpanlessEq,
}; };
use if_chain::if_chain;
use matches::matches;
use rustc::hir;
use rustc::hir::def::Def;
use rustc::lint::{in_external_macro, LateContext, LateLintPass, Lint, LintArray, LintContext, LintPass};
use rustc::ty::{self, Predicate, Ty};
use rustc::{declare_tool_lint, lint_array};
use rustc_errors::Applicability;
use std::borrow::Cow;
use std::fmt;
use std::iter;
use syntax::ast;
use syntax::source_map::{BytePos, Span};
use syntax::symbol::LocalInternedString;
mod option_map_unwrap_or;
mod unnecessary_filter_map;
#[derive(Clone)] #[derive(Clone)]
pub struct Pass; pub struct Pass;
@ -55,7 +57,7 @@ declare_clippy_lint! {
/// and propagate errors upwards with `try!`. /// and propagate errors upwards with `try!`.
/// ///
/// Even if you want to panic on errors, not all `Error`s implement good /// Even if you want to panic on errors, not all `Error`s implement good
/// messages on display. Therefore it may be beneficial to look at the places /// messages on display. Therefore, it may be beneficial to look at the places
/// where they may get displayed. Activate this lint to do just that. /// where they may get displayed. Activate this lint to do just that.
/// ///
/// **Known problems:** None. /// **Known problems:** None.
@ -399,7 +401,7 @@ declare_clippy_lint! {
declare_clippy_lint! { declare_clippy_lint! {
/// **What it does:** Checks for usage of `.clone()` on a ref-counted pointer, /// **What it does:** Checks for usage of `.clone()` on a ref-counted pointer,
/// (`Rc`, `Arc`, `rc::Weak`, or `sync::Weak`), and suggests calling Clone via unified /// (`Rc`, `Arc`, `rc::Weak`, or `sync::Weak`), and suggests calling Clone via unified
/// function syntax instead (e.g. `Rc::clone(foo)`). /// function syntax instead (e.g., `Rc::clone(foo)`).
/// ///
/// **Why is this bad?** Calling '.clone()' on an Rc, Arc, or Weak /// **Why is this bad?** Calling '.clone()' on an Rc, Arc, or Weak
/// can obscure the fact that only the pointer is being cloned, not the underlying /// can obscure the fact that only the pointer is being cloned, not the underlying
@ -458,7 +460,7 @@ declare_clippy_lint! {
declare_clippy_lint! { declare_clippy_lint! {
/// **What it does:** Checks for string methods that receive a single-character /// **What it does:** Checks for string methods that receive a single-character
/// `str` as an argument, e.g. `_.split("x")`. /// `str` as an argument, e.g., `_.split("x")`.
/// ///
/// **Why is this bad?** Performing these methods using a `char` is faster than /// **Why is this bad?** Performing these methods using a `char` is faster than
/// using a `str`. /// using a `str`.
@ -469,7 +471,7 @@ declare_clippy_lint! {
/// `_.split("x")` could be `_.split('x')` /// `_.split("x")` could be `_.split('x')`
pub SINGLE_CHAR_PATTERN, pub SINGLE_CHAR_PATTERN,
perf, perf,
"using a single-character str where a char could be used, e.g. `_.split(\"x\")`" "using a single-character str where a char could be used, e.g., `_.split(\"x\")`"
} }
declare_clippy_lint! { declare_clippy_lint! {
@ -1008,7 +1010,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
/// Checks for the `OR_FUN_CALL` lint. /// Checks for the `OR_FUN_CALL` lint.
#[allow(clippy::too_many_lines)] #[allow(clippy::too_many_lines)]
fn lint_or_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: Span, name: &str, args: &[hir::Expr]) { fn lint_or_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: Span, name: &str, args: &[hir::Expr]) {
/// Check for `unwrap_or(T::new())` or `unwrap_or(T::default())`. /// Checks for `unwrap_or(T::new())` or `unwrap_or(T::default())`.
fn check_unwrap_or_default( fn check_unwrap_or_default(
cx: &LateContext<'_, '_>, cx: &LateContext<'_, '_>,
name: &str, name: &str,
@ -1057,7 +1059,7 @@ fn lint_or_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: Spa
false false
} }
/// Check for `*or(foo())`. /// Checks for `*or(foo())`.
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
fn check_general_case( fn check_general_case(
cx: &LateContext<'_, '_>, cx: &LateContext<'_, '_>,
@ -1546,7 +1548,7 @@ fn lint_unnecessary_fold(cx: &LateContext<'_, '_>, expr: &hir::Expr, fold_args:
cx, cx,
UNNECESSARY_FOLD, UNNECESSARY_FOLD,
fold_span, fold_span,
// TODO #2371 don't suggest e.g. .any(|x| f(x)) if we can suggest .any(f) // TODO #2371 don't suggest e.g., .any(|x| f(x)) if we can suggest .any(f)
"this `.fold` can be written more succinctly using another method", "this `.fold` can be written more succinctly using another method",
"try", "try",
sugg, sugg,
@ -2348,7 +2350,7 @@ impl SelfKind {
// Self types in the HIR are desugared to explicit self types. So it will // Self types in the HIR are desugared to explicit self types. So it will
// always be `self: // always be `self:
// SomeType`, // SomeType`,
// where SomeType can be `Self` or an explicit impl self type (e.g. `Foo` if // where SomeType can be `Self` or an explicit impl self type (e.g., `Foo` if
// the impl is on `Foo`) // the impl is on `Foo`)
// Thus, we only need to test equality against the impl self type or if it is // Thus, we only need to test equality against the impl self type or if it is
// an explicit // an explicit

View file

@ -1,10 +1,3 @@
use crate::consts::{constant, Constant};
use crate::utils::sugg::Sugg;
use crate::utils::{
get_item_name, get_parent_expr, implements_trait, in_constant, in_macro, is_integer_literal, iter_input_pats,
last_path_segment, match_qpath, match_trait_method, paths, snippet, span_lint, span_lint_and_then, walk_ptrs_ty,
SpanlessEq,
};
use if_chain::if_chain; use if_chain::if_chain;
use matches::matches; use matches::matches;
use rustc::hir::intravisit::FnKind; use rustc::hir::intravisit::FnKind;
@ -16,6 +9,14 @@ use rustc_errors::Applicability;
use syntax::ast::LitKind; use syntax::ast::LitKind;
use syntax::source_map::{ExpnFormat, Span}; use syntax::source_map::{ExpnFormat, Span};
use crate::consts::{constant, Constant};
use crate::utils::{
get_item_name, get_parent_expr, implements_trait, in_constant, in_macro, is_integer_literal, iter_input_pats,
last_path_segment, match_qpath, match_trait_method, paths, snippet, span_lint, span_lint_and_then, walk_ptrs_ty,
SpanlessEq,
};
use crate::utils::sugg::Sugg;
declare_clippy_lint! { declare_clippy_lint! {
/// **What it does:** Checks for function arguments and let bindings denoted as /// **What it does:** Checks for function arguments and let bindings denoted as
/// `ref`. /// `ref`.
@ -31,10 +32,10 @@ declare_clippy_lint! {
/// ///
/// **Known problems:** If the argument is dereferenced within the function, /// **Known problems:** If the argument is dereferenced within the function,
/// removing the `ref` will lead to errors. This can be fixed by removing the /// removing the `ref` will lead to errors. This can be fixed by removing the
/// dereferences, e.g. changing `*x` to `x` within the function. /// dereferences, e.g., changing `*x` to `x` within the function.
/// ///
/// **Example:** /// **Example:**
/// ```ignore /// ```rust
/// fn foo(ref x: u8) -> bool { /// fn foo(ref x: u8) -> bool {
/// .. /// ..
/// } /// }
@ -99,7 +100,7 @@ declare_clippy_lint! {
/// ``` /// ```
pub CMP_OWNED, pub CMP_OWNED,
perf, perf,
"creating owned instances for comparing with others, e.g. `x == \"foo\".to_string()`" "creating owned instances for comparing with others, e.g., `x == \"foo\".to_string()`"
} }
declare_clippy_lint! { declare_clippy_lint! {
@ -552,7 +553,7 @@ fn check_to_owned(cx: &LateContext<'_, '_>, expr: &Expr, other: &Expr) {
lint_span, lint_span,
"this creates an owned instance just for comparison", "this creates an owned instance just for comparison",
|db| { |db| {
// this also catches PartialEq implementations that call to_owned // This also catches `PartialEq` implementations that call `to_owned`.
if other_gets_derefed { if other_gets_derefed {
db.span_label(lint_span, "try implementing the comparison without allocating"); db.span_label(lint_span, "try implementing the comparison without allocating");
return; return;
@ -590,7 +591,7 @@ fn is_used(cx: &LateContext<'_, '_>, expr: &Expr) -> bool {
} }
} }
/// Test whether an expression is in a macro expansion (e.g. something /// Tests whether an expression is in a macro expansion (e.g., something
/// generated by /// generated by
/// `#[derive(...)`] or the like). /// `#[derive(...)`] or the like).
fn in_attributes_expansion(expr: &Expr) -> bool { fn in_attributes_expansion(expr: &Expr) -> bool {
@ -601,7 +602,7 @@ fn in_attributes_expansion(expr: &Expr) -> bool {
.map_or(false, |info| matches!(info.format, ExpnFormat::MacroAttribute(_))) .map_or(false, |info| matches!(info.format, ExpnFormat::MacroAttribute(_)))
} }
/// Test whether `def` is a variable defined outside a macro. /// Tests whether `def` is a variable defined outside a macro.
fn non_macro_local(cx: &LateContext<'_, '_>, def: &def::Def) -> bool { fn non_macro_local(cx: &LateContext<'_, '_>, def: &def::Def) -> bool {
match *def { match *def {
def::Def::Local(id) | def::Def::Upvar(id, _, _) => !in_macro(cx.tcx.hir().span(id)), def::Def::Local(id) | def::Def::Upvar(id, _, _) => !in_macro(cx.tcx.hir().span(id)),

View file

@ -194,7 +194,7 @@ impl LintPass for MiscEarly {
} }
} }
// Used to find `return` statements or equivalents e.g. `?` // Used to find `return` statements or equivalents e.g., `?`
struct ReturnVisitor { struct ReturnVisitor {
found_return: bool, found_return: bool,
} }

View file

@ -20,7 +20,7 @@ declare_clippy_lint! {
/// ``` /// ```
pub MUT_MUT, pub MUT_MUT,
pedantic, pedantic,
"usage of double-mut refs, e.g. `&mut &mut ...`" "usage of double-mut refs, e.g., `&mut &mut ...`"
} }
#[derive(Copy, Clone)] #[derive(Copy, Clone)]

View file

@ -33,7 +33,7 @@ declare_clippy_lint! {
/// ``` /// ```
pub NEEDLESS_BOOL, pub NEEDLESS_BOOL,
complexity, complexity,
"if-statements with plain booleans in the then- and else-clause, e.g. `if p { true } else { false }`" "if-statements with plain booleans in the then- and else-clause, e.g., `if p { true } else { false }`"
} }
declare_clippy_lint! { declare_clippy_lint! {
@ -51,7 +51,7 @@ declare_clippy_lint! {
/// ``` /// ```
pub BOOL_COMPARISON, pub BOOL_COMPARISON,
complexity, complexity,
"comparing a variable to a boolean, e.g. `if x == true` or `if x != true`" "comparing a variable to a boolean, e.g., `if x == true` or `if x != true`"
} }
#[derive(Copy, Clone)] #[derive(Copy, Clone)]

View file

@ -176,7 +176,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue {
// //
// * Exclude a type that is specifically bounded by `Borrow`. // * Exclude a type that is specifically bounded by `Borrow`.
// * Exclude a type whose reference also fulfills its bound. (e.g. `std::convert::AsRef`, // * Exclude a type whose reference also fulfills its bound. (e.g., `std::convert::AsRef`,
// `serde::Serialize`) // `serde::Serialize`)
let (implements_borrow_trait, all_borrowable_trait) = { let (implements_borrow_trait, all_borrowable_trait) = {
let preds = preds let preds = preds

View file

@ -8,7 +8,7 @@ use crate::utils::{self, paths, span_lint};
declare_clippy_lint! { declare_clippy_lint! {
/// **What it does:** /// **What it does:**
/// Checks for the usage of negated comparison operators on types which only implement /// Checks for the usage of negated comparison operators on types which only implement
/// `PartialOrd` (e.g. `f64`). /// `PartialOrd` (e.g., `f64`).
/// ///
/// **Why is this bad?** /// **Why is this bad?**
/// These operators make it easy to forget that the underlying types actually allow not only three /// These operators make it easy to forget that the underlying types actually allow not only three

View file

@ -1,8 +1,9 @@
//! Checks for uses of const which the type is not Freeze (Cell-free). //! Checks for uses of const which the type is not `Freeze` (`Cell`-free).
//! //!
//! This lint is **deny** by default. //! This lint is **deny** by default.
use crate::utils::{in_constant, in_macro, is_copy, span_lint_and_then}; use std::ptr;
use rustc::hir::def::Def; use rustc::hir::def::Def;
use rustc::hir::*; use rustc::hir::*;
use rustc::lint::{LateContext, LateLintPass, Lint, LintArray, LintPass}; use rustc::lint::{LateContext, LateLintPass, Lint, LintArray, LintPass};
@ -11,14 +12,15 @@ use rustc::ty::{self, TypeFlags};
use rustc::{declare_tool_lint, lint_array}; use rustc::{declare_tool_lint, lint_array};
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_typeck::hir_ty_to_ty; use rustc_typeck::hir_ty_to_ty;
use std::ptr;
use syntax_pos::{Span, DUMMY_SP}; use syntax_pos::{Span, DUMMY_SP};
use crate::utils::{in_constant, in_macro, is_copy, span_lint_and_then};
declare_clippy_lint! { declare_clippy_lint! {
/// **What it does:** Checks for declaration of `const` items which is interior /// **What it does:** Checks for declaration of `const` items which is interior
/// mutable (e.g. contains a `Cell`, `Mutex`, `AtomicXxxx` etc). /// mutable (e.g., contains a `Cell`, `Mutex`, `AtomicXxxx`, etc.).
/// ///
/// **Why is this bad?** Consts are copied everywhere they are referenced, i.e. /// **Why is this bad?** Consts are copied everywhere they are referenced, i.e.,
/// every time you refer to the const a fresh instance of the `Cell` or `Mutex` /// every time you refer to the const a fresh instance of the `Cell` or `Mutex`
/// or `AtomicXxxx` will be created, which defeats the whole purpose of using /// or `AtomicXxxx` will be created, which defeats the whole purpose of using
/// these types in the first place. /// these types in the first place.
@ -27,7 +29,7 @@ declare_clippy_lint! {
/// variable is wanted, or replaced by a `const fn` if a constructor is wanted. /// variable is wanted, or replaced by a `const fn` if a constructor is wanted.
/// ///
/// **Known problems:** A "non-constant" const item is a legacy way to supply an /// **Known problems:** A "non-constant" const item is a legacy way to supply an
/// initialized value to downstream `static` items (e.g. the /// initialized value to downstream `static` items (e.g., the
/// `std::sync::ONCE_INIT` constant). In this case the use of `const` is legit, /// `std::sync::ONCE_INIT` constant). In this case the use of `const` is legit,
/// and this lint should be suppressed. /// and this lint should be suppressed.
/// ///
@ -51,10 +53,10 @@ declare_clippy_lint! {
} }
declare_clippy_lint! { declare_clippy_lint! {
/// **What it does:** Checks if `const` items which is interior mutable (e.g. /// **What it does:** Checks if `const` items which is interior mutable (e.g.,
/// contains a `Cell`, `Mutex`, `AtomicXxxx` etc) has been borrowed directly. /// contains a `Cell`, `Mutex`, `AtomicXxxx`, etc.) has been borrowed directly.
/// ///
/// **Why is this bad?** Consts are copied everywhere they are referenced, i.e. /// **Why is this bad?** Consts are copied everywhere they are referenced, i.e.,
/// every time you refer to the const a fresh instance of the `Cell` or `Mutex` /// every time you refer to the const a fresh instance of the `Cell` or `Mutex`
/// or `AtomicXxxx` will be created, which defeats the whole purpose of using /// or `AtomicXxxx` will be created, which defeats the whole purpose of using
/// these types in the first place. /// these types in the first place.
@ -108,8 +110,8 @@ impl Source {
fn verify_ty_bound<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: ty::Ty<'tcx>, source: Source) { fn verify_ty_bound<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: ty::Ty<'tcx>, source: Source) {
if ty.is_freeze(cx.tcx, cx.param_env, DUMMY_SP) || is_copy(cx, ty) { if ty.is_freeze(cx.tcx, cx.param_env, DUMMY_SP) || is_copy(cx, ty) {
// an UnsafeCell is !Copy, and an UnsafeCell is also the only type which // An `UnsafeCell` is `!Copy`, and an `UnsafeCell` is also the only type which
// is !Freeze, thus if our type is Copy we can be sure it must be Freeze // is `!Freeze`, thus if our type is `Copy` we can be sure it must be `Freeze`
// as well. // as well.
return; return;
} }
@ -179,7 +181,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonCopyConst {
if let ImplItemKind::Const(hir_ty, ..) = &impl_item.node { if let ImplItemKind::Const(hir_ty, ..) = &impl_item.node {
let item_hir_id = cx.tcx.hir().get_parent_node_by_hir_id(impl_item.hir_id); let item_hir_id = cx.tcx.hir().get_parent_node_by_hir_id(impl_item.hir_id);
let item = cx.tcx.hir().expect_item_by_hir_id(item_hir_id); let item = cx.tcx.hir().expect_item_by_hir_id(item_hir_id);
// ensure the impl is an inherent impl. // Ensure the impl is an inherent impl.
if let ItemKind::Impl(_, _, _, _, None, _, _) = item.node { if let ItemKind::Impl(_, _, _, _, None, _, _) = item.node {
let ty = hir_ty_to_ty(cx.tcx, hir_ty); let ty = hir_ty_to_ty(cx.tcx, hir_ty);
verify_ty_bound( verify_ty_bound(
@ -201,13 +203,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonCopyConst {
return; return;
} }
// make sure it is a const item. // Make sure it is a const item.
match cx.tables.qpath_def(qpath, expr.hir_id) { match cx.tables.qpath_def(qpath, expr.hir_id) {
Def::Const(_) | Def::AssociatedConst(_) => {}, Def::Const(_) | Def::AssociatedConst(_) => {},
_ => return, _ => return,
}; };
// climb up to resolve any field access and explicit referencing. // Climb up to resolve any field access and explicit referencing.
let mut cur_expr = expr; let mut cur_expr = expr;
let mut dereferenced_expr = expr; let mut dereferenced_expr = expr;
let mut needs_check_adjustment = true; let mut needs_check_adjustment = true;
@ -219,7 +221,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonCopyConst {
if let Some(Node::Expr(parent_expr)) = cx.tcx.hir().find_by_hir_id(parent_id) { if let Some(Node::Expr(parent_expr)) = cx.tcx.hir().find_by_hir_id(parent_id) {
match &parent_expr.node { match &parent_expr.node {
ExprKind::AddrOf(..) => { ExprKind::AddrOf(..) => {
// `&e` => `e` must be referenced // `&e` => `e` must be referenced.
needs_check_adjustment = false; needs_check_adjustment = false;
}, },
ExprKind::Field(..) => { ExprKind::Field(..) => {
@ -260,7 +262,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonCopyConst {
adjustments[i - 1].target adjustments[i - 1].target
} }
} else { } else {
// No borrow adjustments = the entire const is moved. // No borrow adjustments means the entire const is moved.
return; return;
} }
} else { } else {

View file

@ -1,19 +1,19 @@
use crate::utils::sugg::Sugg;
use if_chain::if_chain; use if_chain::if_chain;
use rustc::{declare_tool_lint, lint_array};
use rustc::hir::def::Def; use rustc::hir::def::Def;
use rustc::hir::*; use rustc::hir::*;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::{declare_tool_lint, lint_array}; use rustc_errors::Applicability;
use syntax::ptr::P; use syntax::ptr::P;
use crate::utils::paths::*;
use crate::utils::{match_def_path, match_type, span_lint_and_then, SpanlessEq}; use crate::utils::{match_def_path, match_type, span_lint_and_then, SpanlessEq};
use rustc_errors::Applicability; use crate::utils::paths::*;
use crate::utils::sugg::Sugg;
declare_clippy_lint! { declare_clippy_lint! {
/// **What it does:** Checks for expressions that could be replaced by the question mark operator /// **What it does:** Checks for expressions that could be replaced by the question mark operator.
/// ///
/// **Why is this bad?** Question mark usage is more idiomatic /// **Why is this bad?** Question mark usage is more idiomatic.
/// ///
/// **Known problems:** None /// **Known problems:** None
/// ///
@ -48,11 +48,11 @@ impl LintPass for Pass {
} }
impl Pass { impl Pass {
/// Check if the given expression on the given context matches the following structure: /// Checks if the given expression on the given context matches the following structure:
/// ///
/// ```ignore /// ```ignore
/// if option.is_none() { /// if option.is_none() {
/// return None; /// return `None`;
/// } /// }
/// ``` /// ```
/// ///

View file

@ -1,6 +1,3 @@
use crate::utils::sugg::Sugg;
use crate::utils::{get_trait_def_id, higher, implements_trait, SpanlessEq};
use crate::utils::{is_integer_literal, paths, snippet, snippet_opt, span_lint, span_lint_and_then};
use if_chain::if_chain; use if_chain::if_chain;
use rustc::hir::*; use rustc::hir::*;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
@ -9,6 +6,10 @@ use rustc_errors::Applicability;
use syntax::ast::RangeLimits; use syntax::ast::RangeLimits;
use syntax::source_map::Spanned; use syntax::source_map::Spanned;
use crate::utils::sugg::Sugg;
use crate::utils::{get_trait_def_id, higher, implements_trait, SpanlessEq};
use crate::utils::{is_integer_literal, paths, snippet, snippet_opt, span_lint, span_lint_and_then};
declare_clippy_lint! { declare_clippy_lint! {
/// **What it does:** Checks for calling `.step_by(0)` on iterators, /// **What it does:** Checks for calling `.step_by(0)` on iterators,
/// which never terminates. /// which never terminates.
@ -48,7 +49,7 @@ declare_clippy_lint! {
declare_clippy_lint! { declare_clippy_lint! {
/// **What it does:** Checks for exclusive ranges where 1 is added to the /// **What it does:** Checks for exclusive ranges where 1 is added to the
/// upper bound, e.g. `x..(y+1)`. /// upper bound, e.g., `x..(y+1)`.
/// ///
/// **Why is this bad?** The code is more readable with an inclusive range /// **Why is this bad?** The code is more readable with an inclusive range
/// like `x..=y`. /// like `x..=y`.
@ -56,7 +57,7 @@ declare_clippy_lint! {
/// **Known problems:** Will add unnecessary pair of parentheses when the /// **Known problems:** Will add unnecessary pair of parentheses when the
/// expression is not wrapped in a pair but starts with a opening parenthesis /// expression is not wrapped in a pair but starts with a opening parenthesis
/// and ends with a closing one. /// and ends with a closing one.
/// I.e: `let _ = (f()+1)..(f()+1)` results in `let _ = ((f()+1)..=f())`. /// I.e., `let _ = (f()+1)..(f()+1)` results in `let _ = ((f()+1)..=f())`.
/// ///
/// **Example:** /// **Example:**
/// ```rust /// ```rust
@ -69,7 +70,7 @@ declare_clippy_lint! {
declare_clippy_lint! { declare_clippy_lint! {
/// **What it does:** Checks for inclusive ranges where 1 is subtracted from /// **What it does:** Checks for inclusive ranges where 1 is subtracted from
/// the upper bound, e.g. `x..=(y-1)`. /// the upper bound, e.g., `x..=(y-1)`.
/// ///
/// **Why is this bad?** The code is more readable with an exclusive range /// **Why is this bad?** The code is more readable with an exclusive range
/// like `x..y`. /// like `x..y`.
@ -123,16 +124,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
let iter = &args[0].node; let iter = &args[0].node;
let zip_arg = &args[1]; let zip_arg = &args[1];
if_chain! { if_chain! {
// .iter() call // `.iter()` call
if let ExprKind::MethodCall(ref iter_path, _, ref iter_args ) = *iter; if let ExprKind::MethodCall(ref iter_path, _, ref iter_args ) = *iter;
if iter_path.ident.name == "iter"; if iter_path.ident.name == "iter";
// range expression in .zip() call: 0..x.len() // range expression in `.zip()` call: `0..x.len()`
if let Some(higher::Range { start: Some(start), end: Some(end), .. }) = higher::range(cx, zip_arg); if let Some(higher::Range { start: Some(start), end: Some(end), .. }) = higher::range(cx, zip_arg);
if is_integer_literal(start, 0); if is_integer_literal(start, 0);
// .len() call // `.len()` call
if let ExprKind::MethodCall(ref len_path, _, ref len_args) = end.node; if let ExprKind::MethodCall(ref len_path, _, ref len_args) = end.node;
if len_path.ident.name == "len" && len_args.len() == 1; if len_path.ident.name == "len" && len_args.len() == 1;
// .iter() and .len() called on same Path // `.iter()` and `.len()` called on same `Path`
if let ExprKind::Path(QPath::Resolved(_, ref iter_path)) = iter_args[0].node; if let ExprKind::Path(QPath::Resolved(_, ref iter_path)) = iter_args[0].node;
if let ExprKind::Path(QPath::Resolved(_, ref len_path)) = len_args[0].node; if let ExprKind::Path(QPath::Resolved(_, ref len_path)) = len_args[0].node;
if SpanlessEq::new(cx).eq_path_segments(&iter_path.segments, &len_path.segments); if SpanlessEq::new(cx).eq_path_segments(&iter_path.segments, &len_path.segments);
@ -147,7 +148,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
} }
} }
// exclusive range plus one: x..(y+1) // exclusive range plus one: `x..(y+1)`
if_chain! { if_chain! {
if let Some(higher::Range { if let Some(higher::Range {
start, start,
@ -186,7 +187,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
} }
} }
// inclusive range minus one: x..=(y-1) // inclusive range minus one: `x..=(y-1)`
if_chain! { if_chain! {
if let Some(higher::Range { start, end: Some(end), limits: RangeLimits::Closed }) = higher::range(cx, expr); if let Some(higher::Range { start, end: Some(end), limits: RangeLimits::Closed }) = higher::range(cx, expr);
if let Some(y) = y_minus_one(end); if let Some(y) = y_minus_one(end);
@ -213,7 +214,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
} }
fn has_step_by(cx: &LateContext<'_, '_>, expr: &Expr) -> bool { fn has_step_by(cx: &LateContext<'_, '_>, expr: &Expr) -> bool {
// No need for walk_ptrs_ty here because step_by moves self, so it // No need for `walk_ptrs_ty` here because `step_by` moves `self`, so it
// can't be called on a borrowed range. // can't be called on a borrowed range.
let ty = cx.tables.expr_ty_adjusted(expr); let ty = cx.tables.expr_ty_adjusted(expr);

View file

@ -1,4 +1,3 @@
use crate::utils::{in_macro, match_path_ast, snippet_opt, span_lint_and_then, span_note_and_lint};
use if_chain::if_chain; use if_chain::if_chain;
use rustc::lint::{in_external_macro, EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass}; use rustc::lint::{in_external_macro, EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass};
use rustc::{declare_tool_lint, lint_array}; use rustc::{declare_tool_lint, lint_array};
@ -8,6 +7,8 @@ use syntax::source_map::Span;
use syntax::visit::FnKind; use syntax::visit::FnKind;
use syntax_pos::BytePos; use syntax_pos::BytePos;
use crate::utils::{in_macro, match_path_ast, snippet_opt, span_lint_and_then, span_note_and_lint};
declare_clippy_lint! { declare_clippy_lint! {
/// **What it does:** Checks for return statements at the end of a block. /// **What it does:** Checks for return statements at the end of a block.
/// ///
@ -69,7 +70,7 @@ declare_clippy_lint! {
/// statement look like a function call. /// statement look like a function call.
/// ///
/// **Known problems:** The lint currently misses unit return types in types, /// **Known problems:** The lint currently misses unit return types in types,
/// e.g. the `F` in `fn generic_unit<F: Fn() -> ()>(f: F) { .. }`. /// e.g., the `F` in `fn generic_unit<F: Fn() -> ()>(f: F) { .. }`.
/// ///
/// **Example:** /// **Example:**
/// ```rust /// ```rust

View file

@ -24,7 +24,7 @@ declare_clippy_lint! {
/// ``` /// ```
pub SHADOW_SAME, pub SHADOW_SAME,
restriction, restriction,
"rebinding a name to itself, e.g. `let mut x = &mut x`" "rebinding a name to itself, e.g., `let mut x = &mut x`"
} }
declare_clippy_lint! { declare_clippy_lint! {
@ -49,7 +49,7 @@ declare_clippy_lint! {
/// ``` /// ```
pub SHADOW_REUSE, pub SHADOW_REUSE,
restriction, restriction,
"rebinding a name to an expression that re-uses the original value, e.g. `let x = x + 1`" "rebinding a name to an expression that re-uses the original value, e.g., `let x = x + 1`"
} }
declare_clippy_lint! { declare_clippy_lint! {

View file

@ -194,13 +194,13 @@ impl Pass {
struct VectorInitializationVisitor<'a, 'tcx: 'a> { struct VectorInitializationVisitor<'a, 'tcx: 'a> {
cx: &'a LateContext<'a, 'tcx>, cx: &'a LateContext<'a, 'tcx>,
/// Contains the information /// Contains the information.
vec_alloc: VecAllocation<'tcx>, vec_alloc: VecAllocation<'tcx>,
/// Contains, if found, the slow initialization expression /// Contains, the slow initialization expression, if one was found.
slow_expression: Option<InitializationType<'tcx>>, slow_expression: Option<InitializationType<'tcx>>,
/// true if the initialization of the vector has been found on the visited block /// `true` if the initialization of the vector has been found on the visited block.
initialization_found: bool, initialization_found: bool,
} }

View file

@ -1,11 +1,12 @@
use crate::utils::SpanlessEq;
use crate::utils::{get_parent_expr, is_allowed, match_type, paths, span_lint, span_lint_and_sugg, walk_ptrs_ty};
use rustc::hir::*; use rustc::hir::*;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::{declare_tool_lint, lint_array}; use rustc::{declare_tool_lint, lint_array};
use rustc_errors::Applicability; use rustc_errors::Applicability;
use syntax::source_map::Spanned; use syntax::source_map::Spanned;
use crate::utils::SpanlessEq;
use crate::utils::{get_parent_expr, is_allowed, match_type, paths, span_lint, span_lint_and_sugg, walk_ptrs_ty};
declare_clippy_lint! { declare_clippy_lint! {
/// **What it does:** Checks for string appends of the form `x = x + y` (without /// **What it does:** Checks for string appends of the form `x = x + y` (without
/// `let`!). /// `let`!).
@ -35,7 +36,7 @@ declare_clippy_lint! {
/// `Add` implementation is asymmetric (the other operand need not be `String`, /// `Add` implementation is asymmetric (the other operand need not be `String`,
/// but `x` does), while addition as mathematically defined is symmetric, also /// but `x` does), while addition as mathematically defined is symmetric, also
/// the `String::push_str(_)` function is a perfectly good replacement. /// the `String::push_str(_)` function is a perfectly good replacement.
/// Therefore some dislike it and wish not to have it in their code. /// Therefore, some dislike it and wish not to have it in their code.
/// ///
/// That said, other people think that string addition, having a long tradition /// That said, other people think that string addition, having a long tradition
/// in other languages is actually fine, which is why we decided to make this /// in other languages is actually fine, which is why we decided to make this
@ -58,7 +59,7 @@ declare_clippy_lint! {
/// **What it does:** Checks for the `as_bytes` method called on string literals /// **What it does:** Checks for the `as_bytes` method called on string literals
/// that contain only ASCII characters. /// that contain only ASCII characters.
/// ///
/// **Why is this bad?** Byte string literals (e.g. `b"foo"`) can be used /// **Why is this bad?** Byte string literals (e.g., `b"foo"`) can be used
/// instead. They are shorter but less discoverable than `as_bytes()`. /// instead. They are shorter but less discoverable than `as_bytes()`.
/// ///
/// **Known Problems:** None. /// **Known Problems:** None.

View file

@ -485,7 +485,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute {
} }
} }
/// Get the snippet of `Bar` in `…::transmute<Foo, &Bar>`. If that snippet is /// Gets the snippet of `Bar` in `…::transmute<Foo, &Bar>`. If that snippet is
/// not available , use /// not available , use
/// the type's `ToString` implementation. In weird cases it could lead to types /// the type's `ToString` implementation. In weird cases it could lead to types
/// with invalid `'_` /// with invalid `'_`

View file

@ -1,12 +1,9 @@
#![allow(clippy::default_hash_types)] #![allow(clippy::default_hash_types)]
use crate::consts::{constant, Constant}; use std::borrow::Cow;
use crate::utils::paths; use std::cmp::Ordering;
use crate::utils::{ use std::collections::BTreeMap;
clip, comparisons, differing_macro_contexts, higher, in_constant, in_macro, int_bits, last_path_segment,
match_def_path, match_path, multispan_sugg, same_tys, sext, snippet, snippet_opt, snippet_with_applicability,
span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then, unsext, AbsolutePathBuffer,
};
use if_chain::if_chain; use if_chain::if_chain;
use rustc::hir; use rustc::hir;
use rustc::hir::intravisit::{walk_body, walk_expr, walk_ty, FnKind, NestedVisitorMap, Visitor}; use rustc::hir::intravisit::{walk_body, walk_expr, walk_ty, FnKind, NestedVisitorMap, Visitor};
@ -18,13 +15,18 @@ use rustc::{declare_tool_lint, lint_array};
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_target::spec::abi::Abi; use rustc_target::spec::abi::Abi;
use rustc_typeck::hir_ty_to_ty; use rustc_typeck::hir_ty_to_ty;
use std::borrow::Cow;
use std::cmp::Ordering;
use std::collections::BTreeMap;
use syntax::ast::{FloatTy, IntTy, UintTy}; use syntax::ast::{FloatTy, IntTy, UintTy};
use syntax::errors::DiagnosticBuilder; use syntax::errors::DiagnosticBuilder;
use syntax::source_map::Span; use syntax::source_map::Span;
use crate::consts::{constant, Constant};
use crate::utils::paths;
use crate::utils::{
clip, comparisons, differing_macro_contexts, higher, in_constant, in_macro, int_bits, last_path_segment,
match_def_path, match_path, multispan_sugg, same_tys, sext, snippet, snippet_opt, snippet_with_applicability,
span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then, unsext, AbsolutePathBuffer,
};
/// Handles all the linting of funky types /// Handles all the linting of funky types
pub struct TypePass; pub struct TypePass;
@ -174,7 +176,7 @@ impl LintPass for TypePass {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypePass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypePass {
fn check_fn(&mut self, cx: &LateContext<'_, '_>, _: FnKind<'_>, decl: &FnDecl, _: &Body, _: Span, id: HirId) { fn check_fn(&mut self, cx: &LateContext<'_, '_>, _: FnKind<'_>, decl: &FnDecl, _: &Body, _: Span, id: HirId) {
// skip trait implementations, see #605 // Skip trait implementations; see issue #605.
if let Some(hir::Node::Item(item)) = cx.tcx.hir().find_by_hir_id(cx.tcx.hir().get_parent_item(id)) { if let Some(hir::Node::Item(item)) = cx.tcx.hir().find_by_hir_id(cx.tcx.hir().get_parent_item(id)) {
if let ItemKind::Impl(_, _, _, _, Some(..), _, _) = item.node { if let ItemKind::Impl(_, _, _, _, Some(..), _, _) = item.node {
return; return;
@ -213,7 +215,7 @@ fn check_fn_decl(cx: &LateContext<'_, '_>, decl: &FnDecl) {
} }
} }
/// Check if `qpath` has last segment with type parameter matching `path` /// Checks if `qpath` has last segment with type parameter matching `path`
fn match_type_parameter(cx: &LateContext<'_, '_>, qpath: &QPath, path: &[&str]) -> bool { fn match_type_parameter(cx: &LateContext<'_, '_>, qpath: &QPath, path: &[&str]) -> bool {
let last = last_path_segment(qpath); let last = last_path_segment(qpath);
if_chain! { if_chain! {
@ -389,7 +391,7 @@ fn check_ty_rptr(cx: &LateContext<'_, '_>, hir_ty: &hir::Ty, is_local: bool, lt:
}); });
then { then {
if is_any_trait(inner) { if is_any_trait(inner) {
// Ignore `Box<Any>` types, see #1884 for details. // Ignore `Box<Any>` types; see issue #1884 for details.
return; return;
} }
@ -698,7 +700,7 @@ declare_clippy_lint! {
/// ``` /// ```
pub CAST_PRECISION_LOSS, pub CAST_PRECISION_LOSS,
pedantic, pedantic,
"casts that cause loss of precision, e.g. `x as f32` where `x: u64`" "casts that cause loss of precision, e.g., `x as f32` where `x: u64`"
} }
declare_clippy_lint! { declare_clippy_lint! {
@ -719,7 +721,7 @@ declare_clippy_lint! {
/// ``` /// ```
pub CAST_SIGN_LOSS, pub CAST_SIGN_LOSS,
pedantic, pedantic,
"casts from signed types to unsigned types, e.g. `x as u32` where `x: i32`" "casts from signed types to unsigned types, e.g., `x as u32` where `x: i32`"
} }
declare_clippy_lint! { declare_clippy_lint! {
@ -741,13 +743,13 @@ declare_clippy_lint! {
/// ``` /// ```
pub CAST_POSSIBLE_TRUNCATION, pub CAST_POSSIBLE_TRUNCATION,
pedantic, pedantic,
"casts that may cause truncation of the value, e.g. `x as u8` where `x: u32`, or `x as i32` where `x: f32`" "casts that may cause truncation of the value, e.g., `x as u8` where `x: u32`, or `x as i32` where `x: f32`"
} }
declare_clippy_lint! { declare_clippy_lint! {
/// **What it does:** Checks for casts from an unsigned type to a signed type of /// **What it does:** 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, /// 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 /// 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 /// 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 /// for the target signed type. However, the cast works as defined, so this lint
/// is `Allow` by default. /// is `Allow` by default.
@ -764,7 +766,7 @@ declare_clippy_lint! {
/// ``` /// ```
pub CAST_POSSIBLE_WRAP, pub CAST_POSSIBLE_WRAP,
pedantic, pedantic,
"casts that may cause wrapping around the value, e.g. `x as i32` where `x: u32` and `x > i32::MAX`" "casts that may cause wrapping around the value, e.g., `x as i32` where `x: u32` and `x > i32::MAX`"
} }
declare_clippy_lint! { declare_clippy_lint! {
@ -796,7 +798,7 @@ declare_clippy_lint! {
/// ``` /// ```
pub CAST_LOSSLESS, pub CAST_LOSSLESS,
complexity, complexity,
"casts using `as` that are known to be lossless, e.g. `x as u64` where `x: u8`" "casts using `as` that are known to be lossless, e.g., `x as u64` where `x: u8`"
} }
declare_clippy_lint! { declare_clippy_lint! {
@ -812,7 +814,7 @@ declare_clippy_lint! {
/// ``` /// ```
pub UNNECESSARY_CAST, pub UNNECESSARY_CAST,
complexity, complexity,
"cast to the same type, e.g. `x as i32` where `x: i32`" "cast to the same type, e.g., `x as i32` where `x: i32`"
} }
declare_clippy_lint! { declare_clippy_lint! {
@ -1528,14 +1530,14 @@ declare_clippy_lint! {
/// `max < x` are probably mistakes. /// `max < x` are probably mistakes.
/// ///
/// **Known problems:** For `usize` the size of the current compile target will /// **Known problems:** For `usize` the size of the current compile target will
/// be assumed (e.g. 64 bits on 64 bit systems). This means code that uses such /// be assumed (e.g., 64 bits on 64 bit systems). This means code that uses such
/// a comparison to detect target pointer width will trigger this lint. One can /// a comparison to detect target pointer width will trigger this lint. One can
/// use `mem::sizeof` and compare its value or conditional compilation /// use `mem::sizeof` and compare its value or conditional compilation
/// attributes /// attributes
/// like `#[cfg(target_pointer_width = "64")] ..` instead. /// like `#[cfg(target_pointer_width = "64")] ..` instead.
/// ///
/// **Example:** /// **Example:**
/// ```ignore /// ```rust
/// vec.len() <= 0 /// vec.len() <= 0
/// 100 > std::i32::MAX /// 100 > std::i32::MAX
/// ``` /// ```

View file

@ -1,4 +1,3 @@
use crate::utils::span_lint_and_sugg;
use if_chain::if_chain; use if_chain::if_chain;
use rustc::hir::def::{CtorKind, Def}; use rustc::hir::def::{CtorKind, Def};
use rustc::hir::intravisit::{walk_item, walk_path, walk_ty, NestedVisitorMap, Visitor}; use rustc::hir::intravisit::{walk_item, walk_path, walk_ty, NestedVisitorMap, Visitor};
@ -9,6 +8,8 @@ use rustc::{declare_tool_lint, lint_array};
use rustc_errors::Applicability; use rustc_errors::Applicability;
use syntax_pos::symbol::keywords::SelfUpper; use syntax_pos::symbol::keywords::SelfUpper;
use crate::utils::span_lint_and_sugg;
declare_clippy_lint! { declare_clippy_lint! {
/// **What it does:** Checks for unnecessary repetition of structure name when a /// **What it does:** Checks for unnecessary repetition of structure name when a
/// replacement with `Self` is applicable. /// replacement with `Self` is applicable.
@ -60,9 +61,9 @@ impl LintPass for UseSelf {
const SEGMENTS_MSG: &str = "segments should be composed of at least 1 element"; const SEGMENTS_MSG: &str = "segments should be composed of at least 1 element";
fn span_use_self_lint(cx: &LateContext<'_, '_>, path: &Path) { fn span_use_self_lint(cx: &LateContext<'_, '_>, path: &Path) {
// path segments only include actual path, no methods or fields // Path segments only include actual path, no methods or fields.
let last_path_span = path.segments.last().expect(SEGMENTS_MSG).ident.span; let last_path_span = path.segments.last().expect(SEGMENTS_MSG).ident.span;
// only take path up to the end of last_path_span // Only take path up to the end of last_path_span.
let span = path.span.with_hi(last_path_span.hi()); let span = path.span.with_hi(last_path_span.hi());
span_lint_and_sugg( span_lint_and_sugg(
@ -149,7 +150,7 @@ fn check_trait_method_impl_decl<'a, 'tcx: 'a>(
// `impl_decl_ty` (of type `hir::Ty`) represents the type declared in the signature. // `impl_decl_ty` (of type `hir::Ty`) represents the type declared in the signature.
// `impl_ty` (of type `ty:TyS`) is the concrete type that the compiler has determined for // `impl_ty` (of type `ty:TyS`) is the concrete type that the compiler has determined for
// that declaration. We use `impl_decl_ty` to see if the type was declared as `Self` // that declaration. We use `impl_decl_ty` to see if the type was declared as `Self`
// and use `impl_ty` to check its concrete type. // and use `impl_ty` to check its concrete type.
for (impl_decl_ty, (impl_ty, trait_ty)) in impl_decl.inputs.iter().chain(output_ty).zip( for (impl_decl_ty, (impl_ty, trait_ty)) in impl_decl.inputs.iter().chain(output_ty).zip(
impl_method_sig impl_method_sig

View file

@ -1,4 +1,4 @@
/// Return the index of the character after the first camel-case component of /// Returns the index of the character after the first camel-case component of
/// `s`. /// `s`.
pub fn until(s: &str) -> usize { pub fn until(s: &str) -> usize {
let mut iter = s.char_indices(); let mut iter = s.char_indices();
@ -32,7 +32,7 @@ pub fn until(s: &str) -> usize {
} }
} }
/// Return index of the last camel-case component of `s`. /// Returns index of the last camel-case component of `s`.
pub fn from(s: &str) -> usize { pub fn from(s: &str) -> usize {
let mut iter = s.char_indices().rev(); let mut iter = s.char_indices().rev();
if let Some((_, first)) = iter.next() { if let Some((_, first)) = iter.next() {

View file

@ -10,7 +10,7 @@ use std::{env, fmt, fs, io, path};
use syntax::{ast, source_map}; use syntax::{ast, source_map};
use toml; use toml;
/// Get the configuration file from arguments. /// Gets the configuration file from arguments.
pub fn file_from_args( pub fn file_from_args(
args: &[source_map::Spanned<ast::NestedMetaItemKind>], args: &[source_map::Spanned<ast::NestedMetaItemKind>],
) -> Result<Option<path::PathBuf>, (&'static str, source_map::Span)> { ) -> Result<Option<path::PathBuf>, (&'static str, source_map::Span)> {

View file

@ -9,7 +9,7 @@ use rustc::lint::LateContext;
use rustc::{hir, ty}; use rustc::{hir, ty};
use syntax::ast; use syntax::ast;
/// Convert a hir binary operator to the corresponding `ast` type. /// Converts a hir binary operator to the corresponding `ast` type.
pub fn binop(op: hir::BinOpKind) -> ast::BinOpKind { pub fn binop(op: hir::BinOpKind) -> ast::BinOpKind {
match op { match op {
hir::BinOpKind::Eq => ast::BinOpKind::Eq, hir::BinOpKind::Eq => ast::BinOpKind::Eq,
@ -46,7 +46,7 @@ pub struct Range<'a> {
/// Higher a `hir` range to something similar to `ast::ExprKind::Range`. /// Higher a `hir` range to something similar to `ast::ExprKind::Range`.
pub fn range<'a, 'b, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'b hir::Expr) -> Option<Range<'b>> { pub fn range<'a, 'b, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'b hir::Expr) -> Option<Range<'b>> {
/// Find the field named `name` in the field. Always return `Some` for /// Finds the field named `name` in the field. Always return `Some` for
/// convenience. /// convenience.
fn get_field<'a>(name: &str, fields: &'a [hir::Field]) -> Option<&'a hir::Expr> { fn get_field<'a>(name: &str, fields: &'a [hir::Field]) -> Option<&'a hir::Expr> {
let expr = &fields.iter().find(|field| field.ident.name == name)?.expr; let expr = &fields.iter().find(|field| field.ident.name == name)?.expr;

View file

@ -40,7 +40,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
} }
} }
/// Check whether two statements are the same. /// Checks whether two statements are the same.
pub fn eq_stmt(&mut self, left: &Stmt, right: &Stmt) -> bool { pub fn eq_stmt(&mut self, left: &Stmt, right: &Stmt) -> bool {
match (&left.node, &right.node) { match (&left.node, &right.node) {
(&StmtKind::Local(ref l), &StmtKind::Local(ref r)) => { (&StmtKind::Local(ref l), &StmtKind::Local(ref r)) => {
@ -55,7 +55,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
} }
} }
/// Check whether two blocks are the same. /// Checks whether two blocks are the same.
pub fn eq_block(&mut self, left: &Block, right: &Block) -> bool { pub fn eq_block(&mut self, left: &Block, right: &Block) -> bool {
over(&left.stmts, &right.stmts, |l, r| self.eq_stmt(l, r)) over(&left.stmts, &right.stmts, |l, r| self.eq_stmt(l, r))
&& both(&left.expr, &right.expr, |l, r| self.eq_expr(l, r)) && both(&left.expr, &right.expr, |l, r| self.eq_expr(l, r))
@ -186,7 +186,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
left.name == right.name left.name == right.name
} }
/// Check whether two patterns are the same. /// Checks whether two patterns are the same.
pub fn eq_pat(&mut self, left: &Pat, right: &Pat) -> bool { pub fn eq_pat(&mut self, left: &Pat, right: &Pat) -> bool {
match (&left.node, &right.node) { match (&left.node, &right.node) {
(&PatKind::Box(ref l), &PatKind::Box(ref r)) => self.eq_pat(l, r), (&PatKind::Box(ref l), &PatKind::Box(ref r)) => self.eq_pat(l, r),
@ -328,7 +328,7 @@ fn swap_binop<'a>(binop: BinOpKind, lhs: &'a Expr, rhs: &'a Expr) -> Option<(Bin
} }
} }
/// Check if the two `Option`s are both `None` or some equal values as per /// Checks if the two `Option`s are both `None` or some equal values as per
/// `eq_fn`. /// `eq_fn`.
fn both<X, F>(l: &Option<X>, r: &Option<X>, mut eq_fn: F) -> bool fn both<X, F>(l: &Option<X>, r: &Option<X>, mut eq_fn: F) -> bool
where where
@ -338,7 +338,7 @@ where
.map_or_else(|| r.is_none(), |x| r.as_ref().map_or(false, |y| eq_fn(x, y))) .map_or_else(|| r.is_none(), |x| r.as_ref().map_or(false, |y| eq_fn(x, y)))
} }
/// Check if two slices are equal as per `eq_fn`. /// Checks if two slices are equal as per `eq_fn`.
fn over<X, F>(left: &[X], right: &[X], mut eq_fn: F) -> bool fn over<X, F>(left: &[X], right: &[X], mut eq_fn: F) -> bool
where where
F: FnMut(&X, &X) -> bool, F: FnMut(&X, &X) -> bool,

View file

@ -1,30 +1,3 @@
use crate::reexport::*;
use if_chain::if_chain;
use matches::matches;
use rustc::hir;
use rustc::hir::def::Def;
use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
use rustc::hir::intravisit::{NestedVisitorMap, Visitor};
use rustc::hir::Node;
use rustc::hir::*;
use rustc::lint::{LateContext, Level, Lint, LintContext};
use rustc::traits;
use rustc::ty::{
self,
layout::{self, IntegerExt},
subst::Kind,
Binder, Ty, TyCtxt,
};
use rustc_data_structures::sync::Lrc;
use rustc_errors::Applicability;
use std::borrow::Cow;
use std::mem;
use syntax::ast::{self, LitKind};
use syntax::attr;
use syntax::source_map::{Span, DUMMY_SP};
use syntax::symbol;
use syntax::symbol::{keywords, Symbol};
pub mod attrs; pub mod attrs;
pub mod author; pub mod author;
pub mod camel_case; pub mod camel_case;
@ -44,9 +17,37 @@ pub use self::attrs::*;
pub use self::diagnostics::*; pub use self::diagnostics::*;
pub use self::hir_utils::{SpanlessEq, SpanlessHash}; pub use self::hir_utils::{SpanlessEq, SpanlessHash};
/// Returns true if the two spans come from differing expansions (i.e. one is use std::borrow::Cow;
/// from a macro and one use std::mem;
/// isn't).
use if_chain::if_chain;
use matches::matches;
use rustc::hir;
use rustc::hir::def::Def;
use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
use rustc::hir::intravisit::{NestedVisitorMap, Visitor};
use rustc::hir::Node;
use rustc::hir::*;
use rustc::lint::{LateContext, Level, Lint, LintContext};
use rustc::traits;
use rustc::ty::{
self,
layout::{self, IntegerExt},
subst::Kind,
Binder, Ty, TyCtxt,
};
use rustc_data_structures::sync::Lrc;
use rustc_errors::Applicability;
use syntax::ast::{self, LitKind};
use syntax::attr;
use syntax::source_map::{Span, DUMMY_SP};
use syntax::symbol;
use syntax::symbol::{keywords, Symbol};
use crate::reexport::*;
/// Returns `true` if the two spans come from differing expansions (i.e., one is
/// from a macro and one isn't).
pub fn differing_macro_contexts(lhs: Span, rhs: Span) -> bool { pub fn differing_macro_contexts(lhs: Span, rhs: Span) -> bool {
rhs.ctxt() != lhs.ctxt() rhs.ctxt() != lhs.ctxt()
} }
@ -88,7 +89,7 @@ pub fn in_constant(cx: &LateContext<'_, '_>, id: HirId) -> bool {
} }
} }
/// Returns true if this `expn_info` was expanded by any macro. /// Returns `true` if this `expn_info` was expanded by any macro.
pub fn in_macro(span: Span) -> bool { pub fn in_macro(span: Span) -> bool {
span.ctxt().outer().expn_info().is_some() span.ctxt().outer().expn_info().is_some()
} }
@ -112,7 +113,7 @@ impl ty::item_path::ItemPathBuffer for AbsolutePathBuffer {
} }
} }
/// Check if a `DefId`'s path matches the given absolute type path usage. /// Checks if a `DefId`'s path matches the given absolute type path usage.
/// ///
/// # Examples /// # Examples
/// ```rust,ignore /// ```rust,ignore
@ -128,7 +129,7 @@ pub fn match_def_path(tcx: TyCtxt<'_, '_, '_>, def_id: DefId, path: &[&str]) ->
apb.names.len() == path.len() && apb.names.into_iter().zip(path.iter()).all(|(a, &b)| *a == *b) apb.names.len() == path.len() && apb.names.into_iter().zip(path.iter()).all(|(a, &b)| *a == *b)
} }
/// Get the absolute path of `def_id` as a vector of `&str`. /// Gets the absolute path of `def_id` as a vector of `&str`.
/// ///
/// # Examples /// # Examples
/// ```rust,ignore /// ```rust,ignore
@ -146,7 +147,7 @@ pub fn get_def_path(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Vec<&'static str>
.collect() .collect()
} }
/// Check if type is struct, enum or union type with given def path. /// Checks if type is struct, enum or union type with given def path.
pub fn match_type(cx: &LateContext<'_, '_>, ty: Ty<'_>, path: &[&str]) -> bool { pub fn match_type(cx: &LateContext<'_, '_>, ty: Ty<'_>, path: &[&str]) -> bool {
match ty.sty { match ty.sty {
ty::Adt(adt, _) => match_def_path(cx.tcx, adt.did, path), ty::Adt(adt, _) => match_def_path(cx.tcx, adt.did, path),
@ -154,7 +155,7 @@ pub fn match_type(cx: &LateContext<'_, '_>, ty: Ty<'_>, path: &[&str]) -> bool {
} }
} }
/// Check if the method call given in `expr` belongs to given trait. /// Checks if the method call given in `expr` belongs to given trait.
pub fn match_trait_method(cx: &LateContext<'_, '_>, expr: &Expr, path: &[&str]) -> bool { pub fn match_trait_method(cx: &LateContext<'_, '_>, expr: &Expr, path: &[&str]) -> bool {
let method_call = cx.tables.type_dependent_defs()[expr.hir_id]; let method_call = cx.tables.type_dependent_defs()[expr.hir_id];
let trt_id = cx.tcx.trait_of_item(method_call.def_id()); let trt_id = cx.tcx.trait_of_item(method_call.def_id());
@ -165,7 +166,7 @@ pub fn match_trait_method(cx: &LateContext<'_, '_>, expr: &Expr, path: &[&str])
} }
} }
/// Check if an expression references a variable of the given name. /// Checks if an expression references a variable of the given name.
pub fn match_var(expr: &Expr, var: Name) -> bool { pub fn match_var(expr: &Expr, var: Name) -> bool {
if let ExprKind::Path(QPath::Resolved(None, ref path)) = expr.node { if let ExprKind::Path(QPath::Resolved(None, ref path)) = expr.node {
if path.segments.len() == 1 && path.segments[0].ident.name == var { if path.segments.len() == 1 && path.segments[0].ident.name == var {
@ -190,7 +191,7 @@ pub fn single_segment_path(path: &QPath) -> Option<&PathSegment> {
} }
} }
/// Match a `QPath` against a slice of segment string literals. /// Matches a `QPath` against a slice of segment string literals.
/// ///
/// There is also `match_path` if you are dealing with a `rustc::hir::Path` instead of a /// There is also `match_path` if you are dealing with a `rustc::hir::Path` instead of a
/// `rustc::hir::QPath`. /// `rustc::hir::QPath`.
@ -213,7 +214,7 @@ pub fn match_qpath(path: &QPath, segments: &[&str]) -> bool {
} }
} }
/// Match a `Path` against a slice of segment string literals. /// Matches a `Path` against a slice of segment string literals.
/// ///
/// There is also `match_qpath` if you are dealing with a `rustc::hir::QPath` instead of a /// There is also `match_qpath` if you are dealing with a `rustc::hir::QPath` instead of a
/// `rustc::hir::Path`. /// `rustc::hir::Path`.
@ -237,7 +238,7 @@ pub fn match_path(path: &Path, segments: &[&str]) -> bool {
.all(|(a, b)| a.ident.name == *b) .all(|(a, b)| a.ident.name == *b)
} }
/// Match a `Path` against a slice of segment string literals, e.g. /// Matches a `Path` against a slice of segment string literals, e.g.
/// ///
/// # Examples /// # Examples
/// ```rust,ignore /// ```rust,ignore
@ -251,7 +252,7 @@ pub fn match_path_ast(path: &ast::Path, segments: &[&str]) -> bool {
.all(|(a, b)| a.ident.name == *b) .all(|(a, b)| a.ident.name == *b)
} }
/// Get the definition associated to a path. /// Gets the definition associated to a path.
pub fn path_to_def(cx: &LateContext<'_, '_>, path: &[&str]) -> Option<def::Def> { pub fn path_to_def(cx: &LateContext<'_, '_>, path: &[&str]) -> Option<def::Def> {
let crates = cx.tcx.crates(); let crates = cx.tcx.crates();
let krate = crates.iter().find(|&&krate| cx.tcx.crate_name(krate) == path[0]); let krate = crates.iter().find(|&&krate| cx.tcx.crate_name(krate) == path[0]);
@ -298,7 +299,7 @@ pub fn get_trait_def_id(cx: &LateContext<'_, '_>, path: &[&str]) -> Option<DefId
} }
} }
/// Check whether a type implements a trait. /// Checks whether a type implements a trait.
/// See also `get_trait_def_id`. /// See also `get_trait_def_id`.
pub fn implements_trait<'a, 'tcx>( pub fn implements_trait<'a, 'tcx>(
cx: &LateContext<'a, 'tcx>, cx: &LateContext<'a, 'tcx>,
@ -320,7 +321,7 @@ pub fn implements_trait<'a, 'tcx>(
.enter(|infcx| infcx.predicate_must_hold_modulo_regions(&obligation)) .enter(|infcx| infcx.predicate_must_hold_modulo_regions(&obligation))
} }
/// Get the `hir::TraitRef` of the trait the given method is implemented for /// Gets the `hir::TraitRef` of the trait the given method is implemented for.
/// ///
/// Use this if you want to find the `TraitRef` of the `Add` trait in this example: /// Use this if you want to find the `TraitRef` of the `Add` trait in this example:
/// ///
@ -347,7 +348,7 @@ pub fn trait_ref_of_method(cx: &LateContext<'_, '_>, hir_id: HirId) -> Option<Tr
None None
} }
/// Check whether this type implements Drop. /// Checks whether this type implements `Drop`.
pub fn has_drop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool { pub fn has_drop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
match ty.ty_adt_def() { match ty.ty_adt_def() {
Some(def) => def.has_dtor(cx.tcx), Some(def) => def.has_dtor(cx.tcx),
@ -355,12 +356,12 @@ pub fn has_drop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
} }
} }
/// Resolve the definition of a node from its `HirId`. /// Resolves the definition of a node from its `HirId`.
pub fn resolve_node(cx: &LateContext<'_, '_>, qpath: &QPath, id: HirId) -> def::Def { pub fn resolve_node(cx: &LateContext<'_, '_>, qpath: &QPath, id: HirId) -> def::Def {
cx.tables.qpath_def(qpath, id) cx.tables.qpath_def(qpath, id)
} }
/// Return the method names and argument list of nested method call expressions that make up /// Returns the method names and argument list of nested method call expressions that make up
/// `expr`. /// `expr`.
pub fn method_calls<'a>(expr: &'a Expr, max_depth: usize) -> (Vec<Symbol>, Vec<&'a [Expr]>) { pub fn method_calls<'a>(expr: &'a Expr, max_depth: usize) -> (Vec<Symbol>, Vec<&'a [Expr]>) {
let mut method_names = Vec::with_capacity(max_depth); let mut method_names = Vec::with_capacity(max_depth);
@ -383,7 +384,7 @@ pub fn method_calls<'a>(expr: &'a Expr, max_depth: usize) -> (Vec<Symbol>, Vec<&
(method_names, arg_lists) (method_names, arg_lists)
} }
/// Match an `Expr` against a chain of methods, and return the matched `Expr`s. /// Matches an `Expr` against a chain of methods, and return the matched `Expr`s.
/// ///
/// For example, if `expr` represents the `.baz()` in `foo.bar().baz()`, /// For example, if `expr` represents the `.baz()` in `foo.bar().baz()`,
/// `matched_method_chain(expr, &["bar", "baz"])` will return a `Vec` /// `matched_method_chain(expr, &["bar", "baz"])` will return a `Vec`
@ -408,11 +409,12 @@ pub fn method_chain_args<'a>(expr: &'a Expr, methods: &[&str]) -> Option<Vec<&'a
return None; return None;
} }
} }
matched.reverse(); // reverse `matched`, so that it is in the same order as `methods` // Reverse `matched` so that it is in the same order as `methods`.
matched.reverse();
Some(matched) Some(matched)
} }
/// Returns true if the provided `def_id` is an entrypoint to a program /// Returns `true` if the provided `def_id` is an entrypoint to a program.
pub fn is_entrypoint_fn(cx: &LateContext<'_, '_>, def_id: DefId) -> bool { pub fn is_entrypoint_fn(cx: &LateContext<'_, '_>, def_id: DefId) -> bool {
if let Some((entry_fn_def_id, _)) = cx.tcx.entry_fn(LOCAL_CRATE) { if let Some((entry_fn_def_id, _)) = cx.tcx.entry_fn(LOCAL_CRATE) {
return def_id == entry_fn_def_id; return def_id == entry_fn_def_id;
@ -420,7 +422,7 @@ pub fn is_entrypoint_fn(cx: &LateContext<'_, '_>, def_id: DefId) -> bool {
false false
} }
/// Get the name of the item the expression is in, if available. /// Gets the name of the item the expression is in, if available.
pub fn get_item_name(cx: &LateContext<'_, '_>, expr: &Expr) -> Option<Name> { pub fn get_item_name(cx: &LateContext<'_, '_>, expr: &Expr) -> Option<Name> {
let parent_id = cx.tcx.hir().get_parent_item(expr.hir_id); let parent_id = cx.tcx.hir().get_parent_item(expr.hir_id);
match cx.tcx.hir().find_by_hir_id(parent_id) { match cx.tcx.hir().find_by_hir_id(parent_id) {
@ -432,7 +434,7 @@ pub fn get_item_name(cx: &LateContext<'_, '_>, expr: &Expr) -> Option<Name> {
} }
} }
/// Get the name of a `Pat`, if any /// Gets the name of a `Pat`, if any
pub fn get_pat_name(pat: &Pat) -> Option<Name> { pub fn get_pat_name(pat: &Pat) -> Option<Name> {
match pat.node { match pat.node {
PatKind::Binding(.., ref spname, _) => Some(spname.name), PatKind::Binding(.., ref spname, _) => Some(spname.name),
@ -458,14 +460,14 @@ impl<'tcx> Visitor<'tcx> for ContainsName {
} }
} }
/// check if an `Expr` contains a certain name /// Checks if an `Expr` contains a certain name.
pub fn contains_name(name: Name, expr: &Expr) -> bool { pub fn contains_name(name: Name, expr: &Expr) -> bool {
let mut cn = ContainsName { name, result: false }; let mut cn = ContainsName { name, result: false };
cn.visit_expr(expr); cn.visit_expr(expr);
cn.result cn.result
} }
/// Convert a span to a code snippet if available, otherwise use default. /// Converts a span to a code snippet if available, otherwise use default.
/// ///
/// This is useful if you want to provide suggestions for your lint or more generally, if you want /// This is useful if you want to provide suggestions for your lint or more generally, if you want
/// to convert a given `Span` to a `str`. /// to convert a given `Span` to a `str`.
@ -510,12 +512,12 @@ pub fn snippet_with_macro_callsite<'a, 'b, T: LintContext<'b>>(cx: &T, span: Spa
snippet(cx, span.source_callsite(), default) snippet(cx, span.source_callsite(), default)
} }
/// Convert a span to a code snippet. Returns `None` if not available. /// Converts a span to a code snippet. Returns `None` if not available.
pub fn snippet_opt<'a, T: LintContext<'a>>(cx: &T, span: Span) -> Option<String> { pub fn snippet_opt<'a, T: LintContext<'a>>(cx: &T, span: Span) -> Option<String> {
cx.sess().source_map().span_to_snippet(span).ok() cx.sess().source_map().span_to_snippet(span).ok()
} }
/// Convert a span (from a block) to a code snippet if available, otherwise use /// Converts a span (from a block) to a code snippet if available, otherwise use
/// default. /// default.
/// This trims the code of indentation, except for the first line. Use it for /// This trims the code of indentation, except for the first line. Use it for
/// blocks or block-like /// blocks or block-like
@ -612,7 +614,7 @@ fn trim_multiline_inner(s: Cow<'_, str>, ignore_first: bool, ch: char) -> Cow<'_
} }
} }
/// Get a parent expressions if any this is useful to constrain a lint. /// Gets a parent expressions if any this is useful to constrain a lint.
pub fn get_parent_expr<'c>(cx: &'c LateContext<'_, '_>, e: &Expr) -> Option<&'c Expr> { pub fn get_parent_expr<'c>(cx: &'c LateContext<'_, '_>, e: &Expr) -> Option<&'c Expr> {
let map = &cx.tcx.hir(); let map = &cx.tcx.hir();
let hir_id = e.hir_id; let hir_id = e.hir_id;
@ -656,7 +658,7 @@ pub fn get_enclosing_block<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, node: HirId
} }
} }
/// Return the base type for HIR references and pointers. /// Returns the base type for HIR references and pointers.
pub fn walk_ptrs_hir_ty(ty: &hir::Ty) -> &hir::Ty { pub fn walk_ptrs_hir_ty(ty: &hir::Ty) -> &hir::Ty {
match ty.node { match ty.node {
TyKind::Ptr(ref mut_ty) | TyKind::Rptr(_, ref mut_ty) => walk_ptrs_hir_ty(&mut_ty.ty), TyKind::Ptr(ref mut_ty) | TyKind::Rptr(_, ref mut_ty) => walk_ptrs_hir_ty(&mut_ty.ty),
@ -664,7 +666,7 @@ pub fn walk_ptrs_hir_ty(ty: &hir::Ty) -> &hir::Ty {
} }
} }
/// Return the base type for references and raw pointers. /// Returns the base type for references and raw pointers.
pub fn walk_ptrs_ty(ty: Ty<'_>) -> Ty<'_> { pub fn walk_ptrs_ty(ty: Ty<'_>) -> Ty<'_> {
match ty.sty { match ty.sty {
ty::Ref(_, ty, _) => walk_ptrs_ty(ty), ty::Ref(_, ty, _) => walk_ptrs_ty(ty),
@ -672,7 +674,7 @@ pub fn walk_ptrs_ty(ty: Ty<'_>) -> Ty<'_> {
} }
} }
/// Return the base type for references and raw pointers, and count reference /// Returns the base type for references and raw pointers, and count reference
/// depth. /// depth.
pub fn walk_ptrs_ty_depth(ty: Ty<'_>) -> (Ty<'_>, usize) { pub fn walk_ptrs_ty_depth(ty: Ty<'_>) -> (Ty<'_>, usize) {
fn inner(ty: Ty<'_>, depth: usize) -> (Ty<'_>, usize) { fn inner(ty: Ty<'_>, depth: usize) -> (Ty<'_>, usize) {
@ -684,7 +686,7 @@ pub fn walk_ptrs_ty_depth(ty: Ty<'_>) -> (Ty<'_>, usize) {
inner(ty, 0) inner(ty, 0)
} }
/// Check whether the given expression is a constant literal of the given value. /// Checks whether the given expression is a constant literal of the given value.
pub fn is_integer_literal(expr: &Expr, value: u128) -> bool { pub fn is_integer_literal(expr: &Expr, value: u128) -> bool {
// FIXME: use constant folding // FIXME: use constant folding
if let ExprKind::Lit(ref spanned) = expr.node { if let ExprKind::Lit(ref spanned) = expr.node {
@ -706,7 +708,7 @@ pub fn is_adjusted(cx: &LateContext<'_, '_>, e: &Expr) -> bool {
cx.tables.adjustments().get(e.hir_id).is_some() cx.tables.adjustments().get(e.hir_id).is_some()
} }
/// Return the pre-expansion span if is this comes from an expansion of the /// Returns the pre-expansion span if is this comes from an expansion of the
/// macro `name`. /// macro `name`.
/// See also `is_direct_expn_of`. /// See also `is_direct_expn_of`.
pub fn is_expn_of(mut span: Span, name: &str) -> Option<Span> { pub fn is_expn_of(mut span: Span, name: &str) -> Option<Span> {
@ -725,7 +727,7 @@ pub fn is_expn_of(mut span: Span, name: &str) -> Option<Span> {
} }
} }
/// Return the pre-expansion span if is this directly comes from an expansion /// Returns the pre-expansion span if is this directly comes from an expansion
/// of the macro `name`. /// of the macro `name`.
/// The difference with `is_expn_of` is that in /// The difference with `is_expn_of` is that in
/// ```rust,ignore /// ```rust,ignore
@ -754,7 +756,7 @@ pub fn return_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, fn_item: hir::HirId) -> T
cx.tcx.erase_late_bound_regions(&ret_ty) cx.tcx.erase_late_bound_regions(&ret_ty)
} }
/// Check if two types are the same. /// Checks if two types are the same.
/// ///
/// This discards any lifetime annotations, too. /// This discards any lifetime annotations, too.
// FIXME: this works correctly for lifetimes bounds (`for <'a> Foo<'a>` == `for // FIXME: this works correctly for lifetimes bounds (`for <'a> Foo<'a>` == `for
@ -768,7 +770,7 @@ pub fn same_tys<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, a: Ty<'tcx>, b: Ty<'tcx>)
.enter(|infcx| infcx.can_eq(cx.param_env, a, b).is_ok()) .enter(|infcx| infcx.can_eq(cx.param_env, a, b).is_ok())
} }
/// Return whether the given type is an `unsafe` function. /// Returns `true` if the given type is an `unsafe` function.
pub fn type_is_unsafe_function<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool { pub fn type_is_unsafe_function<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
match ty.sty { match ty.sty {
ty::FnDef(..) | ty::FnPtr(_) => ty.fn_sig(cx.tcx).unsafety() == Unsafety::Unsafe, ty::FnDef(..) | ty::FnPtr(_) => ty.fn_sig(cx.tcx).unsafety() == Unsafety::Unsafe,
@ -780,7 +782,7 @@ pub fn is_copy<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
ty.is_copy_modulo_regions(cx.tcx.global_tcx(), cx.param_env, DUMMY_SP) ty.is_copy_modulo_regions(cx.tcx.global_tcx(), cx.param_env, DUMMY_SP)
} }
/// Return whether a pattern is refutable. /// Returns `true` if a pattern is refutable.
pub fn is_refutable(cx: &LateContext<'_, '_>, pat: &Pat) -> bool { pub fn is_refutable(cx: &LateContext<'_, '_>, pat: &Pat) -> bool {
fn is_enum_variant(cx: &LateContext<'_, '_>, qpath: &QPath, id: HirId) -> bool { fn is_enum_variant(cx: &LateContext<'_, '_>, qpath: &QPath, id: HirId) -> bool {
matches!( matches!(
@ -869,7 +871,7 @@ pub fn iter_input_pats<'tcx>(decl: &FnDecl, body: &'tcx Body) -> impl Iterator<I
(0..decl.inputs.len()).map(move |i| &body.arguments[i]) (0..decl.inputs.len()).map(move |i| &body.arguments[i])
} }
/// Check if a given expression is a match expression /// Checks if a given expression is a match expression
/// expanded from `?` operator or `try` macro. /// expanded from `?` operator or `try` macro.
pub fn is_try<'a>(cx: &'_ LateContext<'_, '_>, expr: &'a Expr) -> Option<&'a Expr> { pub fn is_try<'a>(cx: &'_ LateContext<'_, '_>, expr: &'a Expr) -> Option<&'a Expr> {
fn is_ok(cx: &'_ LateContext<'_, '_>, arm: &Arm) -> bool { fn is_ok(cx: &'_ LateContext<'_, '_>, arm: &Arm) -> bool {
@ -916,7 +918,7 @@ pub fn is_try<'a>(cx: &'_ LateContext<'_, '_>, expr: &'a Expr) -> Option<&'a Exp
None None
} }
/// Returns true if the lint is allowed in the current context /// Returns `true` if the lint is allowed in the current context
/// ///
/// Useful for skipping long running code when it's unnecessary /// Useful for skipping long running code when it's unnecessary
pub fn is_allowed(cx: &LateContext<'_, '_>, lint: &'static Lint, id: HirId) -> bool { pub fn is_allowed(cx: &LateContext<'_, '_>, lint: &'static Lint, id: HirId) -> bool {
@ -960,7 +962,7 @@ pub fn clip(tcx: TyCtxt<'_, '_, '_>, u: u128, ity: ast::UintTy) -> u128 {
(u << amt) >> amt (u << amt) >> amt
} }
/// Remove block comments from the given Vec of lines /// Removes block comments from the given `Vec` of lines.
/// ///
/// # Examples /// # Examples
/// ///

View file

@ -240,9 +240,9 @@ impl<'a> Sugg<'a> {
} }
} }
/// Add parenthesis to any expression that might need them. Suitable to the /// Adds parenthesis to any expression that might need them. Suitable to the
/// `self` argument of /// `self` argument of
/// a method call (eg. to build `bar.foo()` or `(1 + 2).foo()`). /// a method call (e.g., to build `bar.foo()` or `(1 + 2).foo()`).
pub fn maybe_par(self) -> Self { pub fn maybe_par(self) -> Self {
match self { match self {
Sugg::NonParen(..) => self, Sugg::NonParen(..) => self,
@ -289,7 +289,7 @@ struct ParenHelper<T> {
} }
impl<T> ParenHelper<T> { impl<T> ParenHelper<T> {
/// Build a `ParenHelper`. /// Builds a `ParenHelper`.
fn new(paren: bool, wrapped: T) -> Self { fn new(paren: bool, wrapped: T) -> Self {
Self { paren, wrapped } Self { paren, wrapped }
} }
@ -305,7 +305,7 @@ impl<T: Display> Display for ParenHelper<T> {
} }
} }
/// Build the string for `<op><expr>` adding parenthesis when necessary. /// Builds the string for `<op><expr>` adding parenthesis when necessary.
/// ///
/// For convenience, the operator is taken as a string because all unary /// For convenience, the operator is taken as a string because all unary
/// operators have the same /// operators have the same
@ -314,7 +314,7 @@ pub fn make_unop(op: &str, expr: Sugg<'_>) -> Sugg<'static> {
Sugg::MaybeParen(format!("{}{}", op, expr.maybe_par()).into()) Sugg::MaybeParen(format!("{}{}", op, expr.maybe_par()).into())
} }
/// Build the string for `<lhs> <op> <rhs>` adding parenthesis when necessary. /// Builds the string for `<lhs> <op> <rhs>` adding parenthesis when necessary.
/// ///
/// Precedence of shift operator relative to other arithmetic operation is /// Precedence of shift operator relative to other arithmetic operation is
/// often confusing so /// often confusing so
@ -413,7 +413,7 @@ enum Associativity {
Right, Right,
} }
/// Return the associativity/fixity of an operator. The difference with /// Returns the associativity/fixity of an operator. The difference with
/// `AssocOp::fixity` is that /// `AssocOp::fixity` is that
/// an operator can be both left and right associative (such as `+`: /// an operator can be both left and right associative (such as `+`:
/// `a + b + c == (a + b) + c == a + (b + c)`. /// `a + b + c == (a + b) + c == a + (b + c)`.
@ -433,7 +433,7 @@ fn associativity(op: &AssocOp) -> Associativity {
} }
} }
/// Convert a `hir::BinOp` to the corresponding assigning binary operator. /// Converts a `hir::BinOp` to the corresponding assigning binary operator.
fn hirbinop2assignop(op: hir::BinOp) -> AssocOp { fn hirbinop2assignop(op: hir::BinOp) -> AssocOp {
use syntax::parse::token::BinOpToken::*; use syntax::parse::token::BinOpToken::*;
@ -460,7 +460,7 @@ fn hirbinop2assignop(op: hir::BinOp) -> AssocOp {
}) })
} }
/// Convert an `ast::BinOp` to the corresponding assigning binary operator. /// Converts an `ast::BinOp` to the corresponding assigning binary operator.
fn astbinop2assignop(op: ast::BinOp) -> AssocOp { fn astbinop2assignop(op: ast::BinOp) -> AssocOp {
use syntax::ast::BinOpKind::*; use syntax::ast::BinOpKind::*;
use syntax::parse::token::BinOpToken; use syntax::parse::token::BinOpToken;
@ -480,13 +480,13 @@ fn astbinop2assignop(op: ast::BinOp) -> AssocOp {
}) })
} }
/// Return the indentation before `span` if there are nothing but `[ \t]` /// Returns the indentation before `span` if there are nothing but `[ \t]`
/// before it on its line. /// before it on its line.
fn indentation<'a, T: LintContext<'a>>(cx: &T, span: Span) -> Option<String> { fn indentation<'a, T: LintContext<'a>>(cx: &T, span: Span) -> Option<String> {
let lo = cx.sess().source_map().lookup_char_pos(span.lo()); let lo = cx.sess().source_map().lookup_char_pos(span.lo());
if let Some(line) = lo.file.get_line(lo.line - 1 /* line numbers in `Loc` are 1-based */) { if let Some(line) = lo.file.get_line(lo.line - 1 /* line numbers in `Loc` are 1-based */) {
if let Some((pos, _)) = line.char_indices().find(|&(_, c)| c != ' ' && c != '\t') { if let Some((pos, _)) = line.char_indices().find(|&(_, c)| c != ' ' && c != '\t') {
// we can mix char and byte positions here because we only consider `[ \t]` // We can mix char and byte positions here because we only consider `[ \t]`.
if lo.col == CharPos(pos) { if lo.col == CharPos(pos) {
Some(line[..pos].into()) Some(line[..pos].into())
} else { } else {

View file

@ -1,7 +1,6 @@
use rustc::lint::LateContext;
use rustc::hir::def::Def; use rustc::hir::def::Def;
use rustc::hir::*; use rustc::hir::*;
use rustc::lint::LateContext;
use rustc::middle::expr_use_visitor::*; use rustc::middle::expr_use_visitor::*;
use rustc::middle::mem_categorization::cmt_; use rustc::middle::mem_categorization::cmt_;
use rustc::middle::mem_categorization::Categorization; use rustc::middle::mem_categorization::Categorization;
@ -9,7 +8,7 @@ use rustc::ty;
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxHashSet;
use syntax::source_map::Span; use syntax::source_map::Span;
/// Returns a set of mutated local variable ids or None if mutations could not be determined. /// Returns a set of mutated local variable IDs, or `None` if mutations could not be determined.
pub fn mutated_variables<'a, 'tcx: 'a>(expr: &'tcx Expr, cx: &'a LateContext<'a, 'tcx>) -> Option<FxHashSet<HirId>> { pub fn mutated_variables<'a, 'tcx: 'a>(expr: &'tcx Expr, cx: &'a LateContext<'a, 'tcx>) -> Option<FxHashSet<HirId>> {
let mut delegate = MutVarsDelegate { let mut delegate = MutVarsDelegate {
used_mutably: FxHashSet::default(), used_mutably: FxHashSet::default(),

View file

@ -106,7 +106,7 @@ fn check_vec_macro<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, vec_args: &higher::VecA
); );
} }
/// Return the item type of the vector (ie. the `T` in `Vec<T>`). /// Returns the item type of the vector (i.e., the `T` in `Vec<T>`).
fn vec_type(ty: Ty<'_>) -> Ty<'_> { fn vec_type(ty: Ty<'_>) -> Ty<'_> {
if let ty::Adt(_, substs) = ty.sty { if let ty::Adt(_, substs) = ty.sty {
substs.type_at(0) substs.type_at(0)

View file

@ -4,7 +4,7 @@
#![allow(clippy::missing_docs_in_private_items)] #![allow(clippy::missing_docs_in_private_items)]
// FIXME: switch to something more ergonomic here, once available. // FIXME: switch to something more ergonomic here, once available.
// (currently there is no way to opt into sysroot crates w/o `extern crate`) // (Currently there is no way to opt into sysroot crates without `extern crate`.)
#[allow(unused_extern_crates)] #[allow(unused_extern_crates)]
extern crate rustc_driver; extern crate rustc_driver;
#[allow(unused_extern_crates)] #[allow(unused_extern_crates)]

View file

@ -5,7 +5,7 @@
#![warn(rust_2018_idioms)] #![warn(rust_2018_idioms)]
// FIXME: switch to something more ergonomic here, once available. // FIXME: switch to something more ergonomic here, once available.
// (currently there is no way to opt into sysroot crates w/o `extern crate`) // (Currently there is no way to opt into sysroot crates without `extern crate`.)
#[allow(unused_extern_crates)] #[allow(unused_extern_crates)]
extern crate rustc_driver; extern crate rustc_driver;
#[allow(unused_extern_crates)] #[allow(unused_extern_crates)]

View file

@ -49,7 +49,7 @@ fn pred_test() {
let v = 3; let v = 3;
let sky = "blue"; let sky = "blue";
// this is a sneaky case, where the block isn't directly in the condition, but is actually // this is a sneaky case, where the block isn't directly in the condition, but is actually
// inside a closure that the condition is using. same principle applies. add some extra , andadd some extra
// expressions to make sure linter isn't confused by them. // expressions to make sure linter isn't confused by them.
if v == 3 if v == 3
&& sky == "blue" && sky == "blue"

View file

@ -12,7 +12,7 @@ fn main() {
(&1u8 as *const u8) as *const u16; (&1u8 as *const u8) as *const u16;
(&mut 1u8 as *mut u8) as *mut u16; (&mut 1u8 as *mut u8) as *mut u16;
/* These should be okay */ /* These should be ok */
// not a pointer type // not a pointer type
1u8 as u16; 1u8 as u16;

View file

@ -2,8 +2,8 @@
#![allow(clippy::no_effect)] #![allow(clippy::no_effect)]
extern "C" { extern "C" {
// NB. Mutability can be easily incorrect in FFI calls, as // N.B., mutability can be easily incorrect in FFI calls -- as
// in C, the default are mutable pointers. // in C, the default is mutable pointers.
fn ffi(c: *mut u8); fn ffi(c: *mut u8);
fn int_ffi(c: *mut i32); fn int_ffi(c: *mut i32);
} }

View file

@ -9,7 +9,7 @@
/// ///
/// error[E0277]: the trait bound `T: Foo` is not satisfied /// error[E0277]: the trait bound `T: Foo` is not satisfied
/// ///
/// See https://github.com/rust-lang/rust-clippy/issues/2760 // See rust-lang/rust-clippy#2760.
trait Foo { trait Foo {
type Bar; type Bar;

View file

@ -1,6 +1,6 @@
use std::collections::HashSet; use std::collections::HashSet;
/// See https://github.com/rust-lang/rust-clippy/issues/2774 // See rust-lang/rust-clippy#2774.
#[derive(Eq, PartialEq, Debug, Hash)] #[derive(Eq, PartialEq, Debug, Hash)]
pub struct Bar { pub struct Bar {
@ -11,14 +11,14 @@ pub struct Bar {
pub struct Foo {} pub struct Foo {}
#[allow(clippy::implicit_hasher)] #[allow(clippy::implicit_hasher)]
// This should not cause a 'cannot relate bound region' ICE // This should not cause a "cannot relate bound region" ICE.
pub fn add_barfoos_to_foos<'a>(bars: &HashSet<&'a Bar>) { pub fn add_barfoos_to_foos<'a>(bars: &HashSet<&'a Bar>) {
let mut foos = HashSet::new(); let mut foos = HashSet::new();
foos.extend(bars.iter().map(|b| &b.foo)); foos.extend(bars.iter().map(|b| &b.foo));
} }
#[allow(clippy::implicit_hasher)] #[allow(clippy::implicit_hasher)]
// Also this should not cause a 'cannot relate bound region' ICE // Also, this should not cause a "cannot relate bound region" ICE.
pub fn add_barfoos_to_foos2(bars: &HashSet<&Bar>) { pub fn add_barfoos_to_foos2(bars: &HashSet<&Bar>) {
let mut foos = HashSet::new(); let mut foos = HashSet::new();
foos.extend(bars.iter().map(|b| &b.foo)); foos.extend(bars.iter().map(|b| &b.foo));

View file

@ -3,7 +3,7 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
/// Test that we do not lint for unused underscores in a `MacroAttribute` /// Tests that we do not lint for unused underscores in a `MacroAttribute`
/// expansion /// expansion
#[deny(clippy::used_underscore_binding)] #[deny(clippy::used_underscore_binding)]
#[derive(Deserialize)] #[derive(Deserialize)]

View file

@ -12,7 +12,7 @@ trait Foo {
const BAR: Option<LinkedList<u8>>; const BAR: Option<LinkedList<u8>>;
} }
// ok, we dont want to warn for implementations, see #605 // Ok, we dont want to warn for implementations; see issue #605.
impl Foo for LinkedList<u8> { impl Foo for LinkedList<u8> {
fn foo(_: LinkedList<u8>) {} fn foo(_: LinkedList<u8>) {}
const BAR: Option<LinkedList<u8>> = None; const BAR: Option<LinkedList<u8>> = None;

View file

@ -1,4 +1,4 @@
//! This file tests for the DOC_MARKDOWN lint //! This file tests for the `DOC_MARKDOWN` lint.
#![allow(dead_code)] #![allow(dead_code)]
#![warn(clippy::doc_markdown)] #![warn(clippy::doc_markdown)]
@ -6,7 +6,7 @@
#![rustfmt::skip] #![rustfmt::skip]
/// The foo_bar function does _nothing_. See also foo::bar. (note the dot there) /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there)
/// Markdown is _weird_. I mean _really weird_. This \_ is ok. So is `_`. But not Foo::some_fun /// Markdown is _weird_. I mean _really weird_. This \_ is ok. So is `_`. But not Foo::some_fun
/// which should be reported only once despite being __doubly bad__. /// which should be reported only once despite being __doubly bad__.
/// Here be ::a::global:path. /// Here be ::a::global:path.
/// That's not code ~NotInCodeBlock~. /// That's not code ~NotInCodeBlock~.
@ -71,7 +71,7 @@ fn main() {
} }
/// ## CamelCaseThing /// ## CamelCaseThing
/// Talks about `CamelCaseThing`. Titles should be ignored, see issue #897. /// Talks about `CamelCaseThing`. Titles should be ignored; see issue #897.
/// ///
/// # CamelCaseThing /// # CamelCaseThing
/// ///
@ -107,7 +107,7 @@ fn issue883() {
fn multiline() { fn multiline() {
} }
/** E.g. serialization of an empty list: FooBar /** E.g., serialization of an empty list: FooBar
``` ```
That's in a code block: `PackedNode` That's in a code block: `PackedNode`
``` ```
@ -118,7 +118,7 @@ be_sure_we_got_to_the_end_of_it
fn issue1073() { fn issue1073() {
} }
/** E.g. serialization of an empty list: FooBar /** E.g., serialization of an empty list: FooBar
``` ```
That's in a code block: PackedNode That's in a code block: PackedNode
``` ```
@ -129,7 +129,7 @@ be_sure_we_got_to_the_end_of_it
fn issue1073_alt() { fn issue1073_alt() {
} }
/// Test more than three quotes: /// Tests more than three quotes:
/// ```` /// ````
/// DoNotWarn /// DoNotWarn
/// ``` /// ```

View file

@ -21,7 +21,7 @@ LL | /// The foo_bar function does _nothing_. See also foo::bar. (note the dot t
error: you should put `Foo::some_fun` between ticks in the documentation error: you should put `Foo::some_fun` between ticks in the documentation
--> $DIR/doc.rs:9:84 --> $DIR/doc.rs:9:84
| |
LL | /// Markdown is _weird_. I mean _really weird_. This /_ is ok. So is `_`. But not Foo::some_fun LL | /, andThis /_ is ok. So is `_`. But not Foo::some_fun
| ^^^^^^^^^^^^^ | ^^^^^^^^^^^^^
error: you should put `a::global:path` between ticks in the documentation error: you should put `a::global:path` between ticks in the documentation

View file

@ -13,44 +13,44 @@ fn main() {
format!("foo"); format!("foo");
format!("{}", "foo"); format!("{}", "foo");
format!("{:?}", "foo"); // don't warn about debug format!("{:?}", "foo"); // Don't warn about `Debug`.
format!("{:8}", "foo"); format!("{:8}", "foo");
format!("{:width$}", "foo", width = 8); format!("{:width$}", "foo", width = 8);
format!("{:+}", "foo"); // warn when the format makes no difference format!("{:+}", "foo"); // Warn when the format makes no difference.
format!("{:<}", "foo"); // warn when the format makes no difference format!("{:<}", "foo"); // Warn when the format makes no difference.
format!("foo {}", "bar"); format!("foo {}", "bar");
format!("{} bar", "foo"); format!("{} bar", "foo");
let arg: String = "".to_owned(); let arg: String = "".to_owned();
format!("{}", arg); format!("{}", arg);
format!("{:?}", arg); // don't warn about debug format!("{:?}", arg); // Don't warn about debug.
format!("{:8}", arg); format!("{:8}", arg);
format!("{:width$}", arg, width = 8); format!("{:width$}", arg, width = 8);
format!("{:+}", arg); // warn when the format makes no difference format!("{:+}", arg); // Warn when the format makes no difference.
format!("{:<}", arg); // warn when the format makes no difference format!("{:<}", arg); // Warn when the format makes no difference.
format!("foo {}", arg); format!("foo {}", arg);
format!("{} bar", arg); format!("{} bar", arg);
// we dont want to warn for non-string args, see #697 // We dont want to warn for non-string args; see issue #697.
format!("{}", 42); format!("{}", 42);
format!("{:?}", 42); format!("{:?}", 42);
format!("{:+}", 42); format!("{:+}", 42);
format!("foo {}", 42); format!("foo {}", 42);
format!("{} bar", 42); format!("{} bar", 42);
// we only want to warn about `format!` itself // We only want to warn about `format!` itself.
println!("foo"); println!("foo");
println!("{}", "foo"); println!("{}", "foo");
println!("foo {}", "foo"); println!("foo {}", "foo");
println!("{}", 42); println!("{}", 42);
println!("foo {}", 42); println!("foo {}", 42);
// A format! inside a macro should not trigger a warning // A `format!` inside a macro should not trigger a warning.
foo!("should not warn"); foo!("should not warn");
// precision on string means slicing without panicking on size: // Precision on string means slicing without panicking on size.
format!("{:.1}", "foo"); // could be "foo"[..1] format!("{:.1}", "foo"); // could be `"foo"[..1]`
format!("{:.10}", "foo"); // could not be "foo"[..10] format!("{:.10}", "foo"); // could not be `"foo"[..10]`
format!("{:.prec$}", "foo", prec = 1); format!("{:.prec$}", "foo", prec = 1);
format!("{:.prec$}", "foo", prec = 10); format!("{:.prec$}", "foo", prec = 10);

View file

@ -232,7 +232,7 @@ fn if_same_then_else() -> Result<&'static str, ()> {
return Ok(&foo[0..]); return Ok(&foo[0..]);
} }
// false positive if_same_then_else, let(x,y) vs let(y,x), see #3559 // False positive `if_same_then_else`: `let (x, y)` vs. `let (y, x)`; see issue #3559.
if true { if true {
let foo = ""; let foo = "";
let (x, y) = (1, 2); let (x, y) = (1, 2);
@ -244,7 +244,7 @@ fn if_same_then_else() -> Result<&'static str, ()> {
} }
} }
// Issue #2423. This was causing an ICE // Issue #2423. This was causing an ICE.
fn func() { fn func() {
if true { if true {
f(&[0; 62]); f(&[0; 62]);

View file

@ -10,13 +10,13 @@ impl PubOne {
} }
impl PubOne { impl PubOne {
// A second impl for this struct - the error span shouldn't mention this // A second impl for this struct -- the error span shouldn't mention this.
pub fn irrelevant(self: &Self) -> bool { pub fn irrelevant(self: &Self) -> bool {
false false
} }
} }
// Identical to PubOne, but with an allow attribute on the impl complaining len // Identical to `PubOne`, but with an `allow` attribute on the impl complaining `len`.
pub struct PubAllowed; pub struct PubAllowed;
#[allow(clippy::len_without_is_empty)] #[allow(clippy::len_without_is_empty)]
@ -26,8 +26,8 @@ impl PubAllowed {
} }
} }
// No allow attribute on this impl block, but that doesn't matter - we only require one on the // No `allow` attribute on this impl block, but that doesn't matter -- we only require one on the
// impl containing len. // impl containing `len`.
impl PubAllowed { impl PubAllowed {
pub fn irrelevant(self: &Self) -> bool { pub fn irrelevant(self: &Self) -> bool {
false false
@ -38,7 +38,7 @@ struct NotPubOne;
impl NotPubOne { impl NotPubOne {
pub fn len(self: &Self) -> isize { pub fn len(self: &Self) -> isize {
// no error, len is pub but `NotPubOne` is not exported anyway // No error; `len` is pub but `NotPubOne` is not exported anyway.
1 1
} }
} }
@ -47,7 +47,7 @@ struct One;
impl One { impl One {
fn len(self: &Self) -> isize { fn len(self: &Self) -> isize {
// no error, len is private, see #1085 // No error; `len` is private; see issue #1085.
1 1
} }
} }
@ -63,7 +63,8 @@ impl PubTraitsToo for One {
} }
trait TraitsToo { trait TraitsToo {
fn len(self: &Self) -> isize; // no error, len is private, see #1085 fn len(self: &Self) -> isize;
// No error; `len` is private; see issue #1085.
} }
impl TraitsToo for One { impl TraitsToo for One {
@ -130,7 +131,7 @@ pub trait Empty {
} }
pub trait InheritingEmpty: Empty { pub trait InheritingEmpty: Empty {
//must not trigger LEN_WITHOUT_IS_EMPTY // Must not trigger `LEN_WITHOUT_IS_EMPTY`.
fn len(&self) -> isize; fn len(&self) -> isize;
} }
@ -144,13 +145,13 @@ fn main() {
let y = One; let y = One;
if y.len() == 0 { if y.len() == 0 {
//no error because One does not have .is_empty() // No error; `One` does not have `.is_empty()`.
println!("This should not happen either!"); println!("This should not happen either!");
} }
let z: &TraitsToo = &y; let z: &TraitsToo = &y;
if z.len() > 0 { if z.len() > 0 {
//no error, because TraitsToo has no .is_empty() method // No error; `TraitsToo` has no `.is_empty()` method.
println!("Nor should this!"); println!("Nor should this!");
} }
@ -171,11 +172,11 @@ fn main() {
println!("Or this!"); println!("Or this!");
} }
if has_is_empty.len() > 1 { if has_is_empty.len() > 1 {
// no error // No error.
println!("This can happen."); println!("This can happen.");
} }
if has_is_empty.len() <= 1 { if has_is_empty.len() <= 1 {
// no error // No error.
println!("This can happen."); println!("This can happen.");
} }
if 0 == has_is_empty.len() { if 0 == has_is_empty.len() {
@ -194,11 +195,11 @@ fn main() {
println!("Or this!"); println!("Or this!");
} }
if 1 < has_is_empty.len() { if 1 < has_is_empty.len() {
// no error // No error.
println!("This can happen."); println!("This can happen.");
} }
if 1 >= has_is_empty.len() { if 1 >= has_is_empty.len() {
// no error // No error.
println!("This can happen."); println!("This can happen.");
} }
assert!(!has_is_empty.is_empty()); assert!(!has_is_empty.is_empty());
@ -211,7 +212,7 @@ fn main() {
let has_wrong_is_empty = HasWrongIsEmpty; let has_wrong_is_empty = HasWrongIsEmpty;
if has_wrong_is_empty.len() == 0 { if has_wrong_is_empty.len() == 0 {
//no error as HasWrongIsEmpty does not have .is_empty() // No error; `HasWrongIsEmpty` does not have `.is_empty()`.
println!("Or this!"); println!("Or this!");
} }
} }
@ -220,7 +221,7 @@ fn test_slice(b: &[u8]) {
if b.len() != 0 {} if b.len() != 0 {}
} }
// this used to ICE // This used to ICE.
pub trait Foo: Sized {} pub trait Foo: Sized {}
pub trait DependsOnFoo: Foo { pub trait DependsOnFoo: Foo {

View file

@ -5,9 +5,11 @@ fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) {}
fn distinct_and_static<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: &'static u8) {} fn distinct_and_static<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: &'static u8) {}
fn same_lifetime_on_input<'a>(_x: &'a u8, _y: &'a u8) {} // no error, same lifetime on two params // No error; same lifetime on two params.
fn same_lifetime_on_input<'a>(_x: &'a u8, _y: &'a u8) {}
fn only_static_on_input(_x: &u8, _y: &u8, _z: &'static u8) {} // no error, static involved // No error; static involved.
fn only_static_on_input(_x: &u8, _y: &u8, _z: &'static u8) {}
fn mut_and_static_input(_x: &mut u8, _y: &'static str) {} fn mut_and_static_input(_x: &mut u8, _y: &'static str) {}
@ -15,31 +17,36 @@ fn in_and_out<'a>(x: &'a u8, _y: u8) -> &'a u8 {
x x
} }
// No error; multiple input refs.
fn multiple_in_and_out_1<'a>(x: &'a u8, _y: &'a u8) -> &'a u8 { fn multiple_in_and_out_1<'a>(x: &'a u8, _y: &'a u8) -> &'a u8 {
x x
} // no error, multiple input refs }
// No error; multiple input refs.
fn multiple_in_and_out_2<'a, 'b>(x: &'a u8, _y: &'b u8) -> &'a u8 { fn multiple_in_and_out_2<'a, 'b>(x: &'a u8, _y: &'b u8) -> &'a u8 {
x x
} // no error, multiple input refs }
// No error; static involved.
fn in_static_and_out<'a>(x: &'a u8, _y: &'static u8) -> &'a u8 { fn in_static_and_out<'a>(x: &'a u8, _y: &'static u8) -> &'a u8 {
x x
} // no error, static involved }
// No error.
fn deep_reference_1<'a, 'b>(x: &'a u8, _y: &'b u8) -> Result<&'a u8, ()> { fn deep_reference_1<'a, 'b>(x: &'a u8, _y: &'b u8) -> Result<&'a u8, ()> {
Ok(x) Ok(x)
} // no error }
// No error; two input refs.
fn deep_reference_2<'a>(x: Result<&'a u8, &'a u8>) -> &'a u8 { fn deep_reference_2<'a>(x: Result<&'a u8, &'a u8>) -> &'a u8 {
x.unwrap() x.unwrap()
} // no error, two input refs }
fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> { fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> {
Ok(x) Ok(x)
} }
// where clause, but without lifetimes // Where-clause, but without lifetimes.
fn where_clause_without_lt<'a, T>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> fn where_clause_without_lt<'a, T>(x: &'a u8, _y: u8) -> Result<&'a u8, ()>
where where
T: Copy, T: Copy,
@ -49,25 +56,29 @@ where
type Ref<'r> = &'r u8; type Ref<'r> = &'r u8;
fn lifetime_param_1<'a>(_x: Ref<'a>, _y: &'a u8) {} // no error, same lifetime on two params // No error; same lifetime on two params.
fn lifetime_param_1<'a>(_x: Ref<'a>, _y: &'a u8) {}
fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {} fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {}
fn lifetime_param_3<'a, 'b: 'a>(_x: Ref<'a>, _y: &'b u8) {} // no error, bounded lifetime // No error; bounded lifetime.
fn lifetime_param_3<'a, 'b: 'a>(_x: Ref<'a>, _y: &'b u8) {}
// No error; bounded lifetime.
fn lifetime_param_4<'a, 'b>(_x: Ref<'a>, _y: &'b u8) fn lifetime_param_4<'a, 'b>(_x: Ref<'a>, _y: &'b u8)
where where
'b: 'a, 'b: 'a,
{ {
} // no error, bounded lifetime }
struct Lt<'a, I: 'static> { struct Lt<'a, I: 'static> {
x: &'a I, x: &'a I,
} }
// No error; fn bound references `'a`.
fn fn_bound<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I> fn fn_bound<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I>
where where
F: Fn(Lt<'a, I>) -> Lt<'a, I>, // no error, fn bound references 'a F: Fn(Lt<'a, I>) -> Lt<'a, I>,
{ {
unreachable!() unreachable!()
} }
@ -79,8 +90,8 @@ where
unreachable!() unreachable!()
} }
// No error; see below.
fn fn_bound_3<'a, F: FnOnce(&'a i32)>(x: &'a i32, f: F) { fn fn_bound_3<'a, F: FnOnce(&'a i32)>(x: &'a i32, f: F) {
// no error, see below
f(x); f(x);
} }
@ -88,10 +99,11 @@ fn fn_bound_3_cannot_elide() {
let x = 42; let x = 42;
let p = &x; let p = &x;
let mut q = &x; let mut q = &x;
fn_bound_3(p, |y| q = y); // this will fail if we elides lifetimes of `fn_bound_3` // This will fail if we elide lifetimes of `fn_bound_3`.
fn_bound_3(p, |y| q = y);
} }
// no error, multiple input refs // No error; multiple input refs.
fn fn_bound_4<'a, F: FnOnce() -> &'a ()>(cond: bool, x: &'a (), f: F) -> &'a () { fn fn_bound_4<'a, F: FnOnce() -> &'a ()>(cond: bool, x: &'a (), f: F) -> &'a () {
if cond { if cond {
x x
@ -109,20 +121,24 @@ impl X {
&self.x &self.x
} }
// No error; multiple input refs.
fn self_and_in_out<'s, 't>(&'s self, _x: &'t u8) -> &'s u8 { fn self_and_in_out<'s, 't>(&'s self, _x: &'t u8) -> &'s u8 {
&self.x &self.x
} // no error, multiple input refs }
fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) {} fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) {}
fn self_and_same_in<'s>(&'s self, _x: &'s u8) {} // no error, same lifetimes on two params // No error; same lifetimes on two params.
fn self_and_same_in<'s>(&'s self, _x: &'s u8) {}
} }
struct Foo<'a>(&'a u8); struct Foo<'a>(&'a u8);
impl<'a> Foo<'a> { impl<'a> Foo<'a> {
fn self_shared_lifetime(&self, _: &'a u8) {} // no error, lifetime 'a not defined in method // No error; lifetime `'a` not defined in method.
fn self_bound_lifetime<'b: 'a>(&self, _: &'b u8) {} // no error, bounds exist fn self_shared_lifetime(&self, _: &'a u8) {}
// No error; bounds exist.
fn self_bound_lifetime<'b: 'a>(&self, _: &'b u8) {}
} }
fn already_elided<'a>(_: &u8, _: &'a u8) -> &'a u8 { fn already_elided<'a>(_: &u8, _: &'a u8) -> &'a u8 {
@ -133,17 +149,17 @@ fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str {
unimplemented!() unimplemented!()
} }
// no warning, two input lifetimes (named on the reference, anonymous on Foo) // No warning; two input lifetimes (named on the reference, anonymous on `Foo`).
fn struct_with_lt2<'a>(_foo: &'a Foo) -> &'a str { fn struct_with_lt2<'a>(_foo: &'a Foo) -> &'a str {
unimplemented!() unimplemented!()
} }
// no warning, two input lifetimes (anonymous on the reference, named on Foo) // No warning; two input lifetimes (anonymous on the reference, named on `Foo`).
fn struct_with_lt3<'a>(_foo: &Foo<'a>) -> &'a str { fn struct_with_lt3<'a>(_foo: &Foo<'a>) -> &'a str {
unimplemented!() unimplemented!()
} }
// no warning, two input lifetimes // No warning; two input lifetimes.
fn struct_with_lt4<'a, 'b>(_foo: &'a Foo<'b>) -> &'a str { fn struct_with_lt4<'a, 'b>(_foo: &'a Foo<'b>) -> &'a str {
unimplemented!() unimplemented!()
} }
@ -152,13 +168,13 @@ trait WithLifetime<'a> {}
type WithLifetimeAlias<'a> = WithLifetime<'a>; type WithLifetimeAlias<'a> = WithLifetime<'a>;
// should not warn because it won't build without the lifetime // Should not warn because it won't build without the lifetime.
fn trait_obj_elided<'a>(_arg: &'a WithLifetime) -> &'a str { fn trait_obj_elided<'a>(_arg: &'a WithLifetime) -> &'a str {
unimplemented!() unimplemented!()
} }
// this should warn because there is no lifetime on Drop, so this would be // Should warn because there is no lifetime on `Drop`, so this would be
// unambiguous if we elided the lifetime // unambiguous if we elided the lifetime.
fn trait_obj_elided2<'a>(_arg: &'a Drop) -> &'a str { fn trait_obj_elided2<'a>(_arg: &'a Drop) -> &'a str {
unimplemented!() unimplemented!()
} }
@ -169,17 +185,17 @@ fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str {
unimplemented!() unimplemented!()
} }
// no warning, two input lifetimes (named on the reference, anonymous on Foo) // No warning; two input lifetimes (named on the reference, anonymous on `FooAlias`).
fn alias_with_lt2<'a>(_foo: &'a FooAlias) -> &'a str { fn alias_with_lt2<'a>(_foo: &'a FooAlias) -> &'a str {
unimplemented!() unimplemented!()
} }
// no warning, two input lifetimes (anonymous on the reference, named on Foo) // No warning; two input lifetimes (anonymous on the reference, named on `FooAlias`).
fn alias_with_lt3<'a>(_foo: &FooAlias<'a>) -> &'a str { fn alias_with_lt3<'a>(_foo: &FooAlias<'a>) -> &'a str {
unimplemented!() unimplemented!()
} }
// no warning, two input lifetimes // No warning; two input lifetimes.
fn alias_with_lt4<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'a str { fn alias_with_lt4<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'a str {
unimplemented!() unimplemented!()
} }
@ -199,12 +215,12 @@ fn trait_bound<'a, T: WithLifetime<'a>>(_: &'a u8, _: T) {
unimplemented!() unimplemented!()
} }
// don't warn on these, see #292 // Don't warn on these; see issue #292.
fn trait_bound_bug<'a, T: WithLifetime<'a>>() { fn trait_bound_bug<'a, T: WithLifetime<'a>>() {
unimplemented!() unimplemented!()
} }
// #740 // See issue #740.
struct Test { struct Test {
vec: Vec<usize>, vec: Vec<usize>,
} }
@ -224,8 +240,7 @@ fn test<'a>(x: &'a [u8]) -> u8 {
*y *y
} }
// #3284 - Give a hint regarding lifetime in return type // Issue #3284: give hint regarding lifetime in return type.
struct Cow<'a> { struct Cow<'a> {
x: &'a str, x: &'a str,
} }

View file

@ -13,7 +13,7 @@ fn ref_pats() {
&None => println!("none"), &None => println!("none"),
} }
match v { match v {
// this doesn't trigger, we have a different pattern // This doesn't trigger; we have a different pattern.
&Some(v) => println!("some"), &Some(v) => println!("some"),
other => println!("other"), other => println!("other"),
} }
@ -23,13 +23,13 @@ fn ref_pats() {
&(v, 1) => println!("{}", v), &(v, 1) => println!("{}", v),
_ => println!("none"), _ => println!("none"),
} }
// special case: using & both in expr and pats // Special case: using `&` both in expr and pats.
let w = Some(0); let w = Some(0);
match &w { match &w {
&Some(v) => println!("{:?}", v), &Some(v) => println!("{:?}", v),
&None => println!("none"), &None => println!("none"),
} }
// false positive: only wildcard pattern // False positive: only wildcard pattern.
let w = Some(0); let w = Some(0);
match w { match w {
_ => println!("none"), _ => println!("none"),
@ -69,14 +69,14 @@ fn match_wild_err_arm() {
}, },
} }
// allowed when not with `panic!` block // Allowed when not with `panic!` block.
match x { match x {
Ok(3) => println!("ok"), Ok(3) => println!("ok"),
Ok(_) => println!("ok"), Ok(_) => println!("ok"),
Err(_) => println!("err"), Err(_) => println!("err"),
} }
// allowed when used with `unreachable!` // Allowed when used with `unreachable!`.
match x { match x {
Ok(3) => println!("ok"), Ok(3) => println!("ok"),
Ok(_) => println!("ok"), Ok(_) => println!("ok"),
@ -97,14 +97,14 @@ fn match_wild_err_arm() {
}, },
} }
// no warning because of the guard // No warning because of the guard.
match x { match x {
Ok(x) if x * x == 64 => println!("ok"), Ok(x) if x * x == 64 => println!("ok"),
Ok(_) => println!("ok"), Ok(_) => println!("ok"),
Err(_) => println!("err"), Err(_) => println!("err"),
} }
// this used to be a false positive, see #1996 // This used to be a false positive; see issue #1996.
match x { match x {
Ok(3) => println!("ok"), Ok(3) => println!("ok"),
Ok(x) if x * x == 64 => println!("ok 64"), Ok(x) if x * x == 64 => println!("ok 64"),
@ -118,14 +118,14 @@ fn match_wild_err_arm() {
_ => println!("err"), _ => println!("err"),
} }
// no warning because of the different types for x // No warning; different types for `x`.
match (x, Some(1.0f64)) { match (x, Some(1.0f64)) {
(Ok(x), Some(_)) => println!("ok {}", x), (Ok(x), Some(_)) => println!("ok {}", x),
(Ok(_), Some(x)) => println!("ok {}", x), (Ok(_), Some(x)) => println!("ok {}", x),
_ => println!("err"), _ => println!("err"),
} }
// because of a bug, no warning was generated for this case before #2251 // Because of a bug, no warning was generated for this case before #2251.
match x { match x {
Ok(_tmp) => println!("ok"), Ok(_tmp) => println!("ok"),
Ok(3) => println!("ok"), Ok(3) => println!("ok"),

View file

@ -49,19 +49,20 @@ impl T {
true true
} }
// no error, self is a ref // No error; self is a ref.
fn sub(&self, other: T) -> &T { fn sub(&self, other: T) -> &T {
self self
} }
// no error, different #arguments // No error; different number of arguments.
fn div(self) -> T { fn div(self) -> T {
self self
} }
fn rem(self, other: T) {} // no error, wrong return type // No error; wrong return type.
fn rem(self, other: T) {}
// fine // Fine
fn into_u32(self) -> u32 { fn into_u32(self) -> u32 {
0 0
} }
@ -84,7 +85,7 @@ struct Lt<'a> {
} }
impl<'a> Lt<'a> { impl<'a> Lt<'a> {
// The lifetime is different, but thats irrelevant, see #734 // The lifetime is different, but thats irrelevant; see issue #734.
#[allow(clippy::needless_lifetimes)] #[allow(clippy::needless_lifetimes)]
pub fn new<'b>(s: &'b str) -> Lt<'b> { pub fn new<'b>(s: &'b str) -> Lt<'b> {
unimplemented!() unimplemented!()
@ -96,7 +97,7 @@ struct Lt2<'a> {
} }
impl<'a> Lt2<'a> { impl<'a> Lt2<'a> {
// The lifetime is different, but thats irrelevant, see #734 // The lifetime is different, but thats irrelevant; see issue #734.
pub fn new(s: &str) -> Lt2 { pub fn new(s: &str) -> Lt2 {
unimplemented!() unimplemented!()
} }
@ -107,7 +108,7 @@ struct Lt3<'a> {
} }
impl<'a> Lt3<'a> { impl<'a> Lt3<'a> {
// The lifetime is different, but thats irrelevant, see #734 // The lifetime is different, but thats irrelevant; see issue #734.
pub fn new() -> Lt3<'static> { pub fn new() -> Lt3<'static> {
unimplemented!() unimplemented!()
} }
@ -120,7 +121,7 @@ impl U {
fn new() -> Self { fn new() -> Self {
U U
} }
// ok because U is Copy // Ok because `U` is `Copy`.
fn to_something(self) -> u32 { fn to_something(self) -> u32 {
0 0
} }
@ -138,7 +139,7 @@ impl<T> V<T> {
impl Mul<T> for T { impl Mul<T> for T {
type Output = T; type Output = T;
// no error, obviously // No error, obviously.
fn mul(self, other: T) -> T { fn mul(self, other: T) -> T {
self self
} }
@ -152,12 +153,12 @@ impl Mul<T> for T {
fn option_methods() { fn option_methods() {
let opt = Some(1); let opt = Some(1);
// Check OPTION_MAP_UNWRAP_OR // Check `OPTION_MAP_UNWRAP_OR`.
// single line case // Single line case.
let _ = opt.map(|x| x + 1) let _ = opt.map(|x| x + 1)
// Should lint even though this call is on a separate line.
.unwrap_or(0); // should lint even though this call is on a separate line .unwrap_or(0);
// multi line cases // Multi-line cases.
let _ = opt.map(|x| { let _ = opt.map(|x| {
x + 1 x + 1
} }
@ -166,9 +167,9 @@ fn option_methods() {
.unwrap_or({ .unwrap_or({
0 0
}); });
// single line `map(f).unwrap_or(None)` case // Single line `map(f).unwrap_or(None)` case.
let _ = opt.map(|x| Some(x + 1)).unwrap_or(None); let _ = opt.map(|x| Some(x + 1)).unwrap_or(None);
// multiline `map(f).unwrap_or(None)` cases // Multi-line `map(f).unwrap_or(None)` cases.
let _ = opt.map(|x| { let _ = opt.map(|x| {
Some(x + 1) Some(x + 1)
} }
@ -189,9 +190,9 @@ fn option_methods() {
// Check OPTION_MAP_UNWRAP_OR_ELSE // Check OPTION_MAP_UNWRAP_OR_ELSE
// single line case // single line case
let _ = opt.map(|x| x + 1) let _ = opt.map(|x| x + 1)
// Should lint even though this call is on a separate line.
.unwrap_or_else(|| 0); // should lint even though this call is on a separate line .unwrap_or_else(|| 0);
// multi line cases // Multi-line cases.
let _ = opt.map(|x| { let _ = opt.map(|x| {
x + 1 x + 1
} }
@ -200,20 +201,21 @@ fn option_methods() {
.unwrap_or_else(|| .unwrap_or_else(||
0 0
); );
// macro case // Macro case.
let _ = opt_map!(opt, |x| x + 1).unwrap_or_else(|| 0); // should not lint // Should not lint.
let _ = opt_map!(opt, |x| x + 1).unwrap_or_else(|| 0);
// Check OPTION_MAP_OR_NONE // Check `OPTION_MAP_OR_NONE`.
// single line case // Single line case.
let _ = opt.map_or(None, |x| Some(x + 1)); let _ = opt.map_or(None, |x| Some(x + 1));
// multi line case // Multi-line case.
let _ = opt.map_or(None, |x| { let _ = opt.map_or(None, |x| {
Some(x + 1) Some(x + 1)
} }
); );
} }
/// Struct to generate false positives for things with .iter() /// Struct to generate false positives for things with `.iter()`.
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
struct HasIter; struct HasIter;
@ -227,65 +229,65 @@ impl HasIter {
} }
} }
/// Checks implementation of `FILTER_NEXT` lint /// Checks implementation of `FILTER_NEXT` lint.
#[rustfmt::skip] #[rustfmt::skip]
fn filter_next() { fn filter_next() {
let v = vec![3, 2, 1, 0, -1, -2, -3]; let v = vec![3, 2, 1, 0, -1, -2, -3];
// check single-line case // Single-line case.
let _ = v.iter().filter(|&x| *x < 0).next(); let _ = v.iter().filter(|&x| *x < 0).next();
// check multi-line case // Multi-line case.
let _ = v.iter().filter(|&x| { let _ = v.iter().filter(|&x| {
*x < 0 *x < 0
} }
).next(); ).next();
// check that we don't lint if the caller is not an Iterator // Check that hat we don't lint if the caller is not an `Iterator`.
let foo = IteratorFalsePositives { foo: 0 }; let foo = IteratorFalsePositives { foo: 0 };
let _ = foo.filter().next(); let _ = foo.filter().next();
} }
/// Checks implementation of `SEARCH_IS_SOME` lint /// Checks implementation of `SEARCH_IS_SOME` lint.
#[rustfmt::skip] #[rustfmt::skip]
fn search_is_some() { fn search_is_some() {
let v = vec![3, 2, 1, 0, -1, -2, -3]; let v = vec![3, 2, 1, 0, -1, -2, -3];
// check `find().is_some()`, single-line // Check `find().is_some()`, single-line case.
let _ = v.iter().find(|&x| *x < 0).is_some(); let _ = v.iter().find(|&x| *x < 0).is_some();
// check `find().is_some()`, multi-line // Check `find().is_some()`, multi-line case.
let _ = v.iter().find(|&x| { let _ = v.iter().find(|&x| {
*x < 0 *x < 0
} }
).is_some(); ).is_some();
// check `position().is_some()`, single-line // Check `position().is_some()`, single-line case.
let _ = v.iter().position(|&x| x < 0).is_some(); let _ = v.iter().position(|&x| x < 0).is_some();
// check `position().is_some()`, multi-line // Check `position().is_some()`, multi-line case.
let _ = v.iter().position(|&x| { let _ = v.iter().position(|&x| {
x < 0 x < 0
} }
).is_some(); ).is_some();
// check `rposition().is_some()`, single-line // Check `rposition().is_some()`, single-line case.
let _ = v.iter().rposition(|&x| x < 0).is_some(); let _ = v.iter().rposition(|&x| x < 0).is_some();
// check `rposition().is_some()`, multi-line // Check `rposition().is_some()`, multi-line case.
let _ = v.iter().rposition(|&x| { let _ = v.iter().rposition(|&x| {
x < 0 x < 0
} }
).is_some(); ).is_some();
// check that we don't lint if the caller is not an Iterator // Check that we don't lint if the caller is not an `Iterator`.
let foo = IteratorFalsePositives { foo: 0 }; let foo = IteratorFalsePositives { foo: 0 };
let _ = foo.find().is_some(); let _ = foo.find().is_some();
let _ = foo.position().is_some(); let _ = foo.position().is_some();
let _ = foo.rposition().is_some(); let _ = foo.rposition().is_some();
} }
/// Checks implementation of the `OR_FUN_CALL` lint /// Checks implementation of the `OR_FUN_CALL` lint.
fn or_fun_call() { fn or_fun_call() {
struct Foo; struct Foo;
@ -348,14 +350,14 @@ fn or_fun_call() {
let _ = stringy.unwrap_or("".to_owned()); let _ = stringy.unwrap_or("".to_owned());
} }
/// Checks implementation of `ITER_NTH` lint /// Checks implementation of `ITER_NTH` lint.
fn iter_nth() { fn iter_nth() {
let mut some_vec = vec![0, 1, 2, 3]; let mut some_vec = vec![0, 1, 2, 3];
let mut boxed_slice: Box<[u8]> = Box::new([0, 1, 2, 3]); let mut boxed_slice: Box<[u8]> = Box::new([0, 1, 2, 3]);
let mut some_vec_deque: VecDeque<_> = some_vec.iter().cloned().collect(); let mut some_vec_deque: VecDeque<_> = some_vec.iter().cloned().collect();
{ {
// Make sure we lint `.iter()` for relevant types // Make sure we lint `.iter()` for relevant types.
let bad_vec = some_vec.iter().nth(3); let bad_vec = some_vec.iter().nth(3);
let bad_slice = &some_vec[..].iter().nth(3); let bad_slice = &some_vec[..].iter().nth(3);
let bad_boxed_slice = boxed_slice.iter().nth(3); let bad_boxed_slice = boxed_slice.iter().nth(3);
@ -363,7 +365,7 @@ fn iter_nth() {
} }
{ {
// Make sure we lint `.iter_mut()` for relevant types // Make sure we lint `.iter_mut()` for relevant types.
let bad_vec = some_vec.iter_mut().nth(3); let bad_vec = some_vec.iter_mut().nth(3);
} }
{ {
@ -373,7 +375,7 @@ fn iter_nth() {
let bad_vec_deque = some_vec_deque.iter_mut().nth(3); let bad_vec_deque = some_vec_deque.iter_mut().nth(3);
} }
// Make sure we don't lint for non-relevant types // Make sure we don't lint for non-relevant types.
let false_positive = HasIter; let false_positive = HasIter;
let ok = false_positive.iter().nth(3); let ok = false_positive.iter().nth(3);
let ok_mut = false_positive.iter_mut().nth(3); let ok_mut = false_positive.iter_mut().nth(3);

View file

@ -14,12 +14,12 @@ fn main() {
let mut var2 = 5; let mut var2 = 5;
let thingy2 = Some(&mut var2); let thingy2 = Some(&mut var2);
if let Some(&mut ref mut v) = thingy2 { if let Some(&mut ref mut v) = thingy2 {
// ^ should *not* be linted // ^ should **not** be linted
// v is borrowed as mutable. // v is borrowed as mutable.
*v = 10; *v = 10;
} }
if let Some(&mut ref v) = thingy2 { if let Some(&mut ref v) = thingy2 {
// ^ should *not* be linted // ^ should **not** be linted
// here, v is borrowed as immutable. // here, v is borrowed as immutable.
// can't do that: // can't do that:
//*v = 15; //*v = 15;
@ -37,7 +37,7 @@ enum Animal {
fn foo(a: &Animal, b: &Animal) { fn foo(a: &Animal, b: &Animal) {
match (a, b) { match (a, b) {
(&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (), // lifetime mismatch error if there is no '&ref' (&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (), // lifetime mismatch error if there is no '&ref'
// ^ and ^ should *not* be linted // ^ and ^ should **not** be linted
(&Animal::Dog(ref a), &Animal::Dog(_)) => (), // ^ should *not* be linted (&Animal::Dog(ref a), &Animal::Dog(_)) => (), // ^ should **not** be linted
} }
} }

View file

@ -20,6 +20,6 @@ fn main() {
let ref mut z = 1 + 2; let ref mut z = 1 + 2;
let (ref x, _) = (1, 2); // okay, not top level let (ref x, _) = (1, 2); // ok, not top level
println!("The answer is {}.", x); println!("The answer is {}.", x);
} }

View file

@ -7,13 +7,13 @@ fn zero() {
#[warn(clippy::unicode_not_nfc)] #[warn(clippy::unicode_not_nfc)]
fn canon() { fn canon() {
print!("̀àh?"); print!("̀àh?");
print!("a\u{0300}h?"); // also okay print!("a\u{0300}h?"); // also ok
} }
#[warn(clippy::non_ascii_literal)] #[warn(clippy::non_ascii_literal)]
fn uni() { fn uni() {
print!("Üben!"); print!("Üben!");
print!("\u{DC}ben!"); // this is okay print!("\u{DC}ben!"); // this is ok
} }
fn main() { fn main() {

View file

@ -9,12 +9,12 @@ macro_rules! test_macro {
}}; }};
} }
/// Test that we lint if we use a binding with a single leading underscore /// Tests that we lint if we use a binding with a single leading underscore
fn prefix_underscore(_foo: u32) -> u32 { fn prefix_underscore(_foo: u32) -> u32 {
_foo + 1 _foo + 1
} }
/// Test that we lint if we use a `_`-variable defined outside within a macro expansion /// Tests that we lint if we use a `_`-variable defined outside within a macro expansion
fn in_macro(_foo: u32) { fn in_macro(_foo: u32) {
println!("{}", _foo); println!("{}", _foo);
assert_eq!(_foo, _foo); assert_eq!(_foo, _foo);
@ -27,23 +27,23 @@ struct StructFieldTest {
_underscore_field: u32, _underscore_field: u32,
} }
/// Test that we lint the use of a struct field which is prefixed with an underscore /// Tests that we lint the use of a struct field which is prefixed with an underscore
fn in_struct_field() { fn in_struct_field() {
let mut s = StructFieldTest { _underscore_field: 0 }; let mut s = StructFieldTest { _underscore_field: 0 };
s._underscore_field += 1; s._underscore_field += 1;
} }
/// Test that we do not lint if the underscore is not a prefix /// Tests that we do not lint if the underscore is not a prefix
fn non_prefix_underscore(some_foo: u32) -> u32 { fn non_prefix_underscore(some_foo: u32) -> u32 {
some_foo + 1 some_foo + 1
} }
/// Test that we do not lint if we do not use the binding (simple case) /// Tests that we do not lint if we do not use the binding (simple case)
fn unused_underscore_simple(_foo: u32) -> u32 { fn unused_underscore_simple(_foo: u32) -> u32 {
1 1
} }
/// Test that we do not lint if we do not use the binding (complex case). This checks for /// Tests that we do not lint if we do not use the binding (complex case). This checks for
/// compatibility with the built-in `unused_variables` lint. /// compatibility with the built-in `unused_variables` lint.
fn unused_underscore_complex(mut _foo: u32) -> u32 { fn unused_underscore_complex(mut _foo: u32) -> u32 {
_foo += 1; _foo += 1;
@ -64,7 +64,7 @@ enum _EnumTest {
_Value(_StructTest), _Value(_StructTest),
} }
/// Test that we do not lint for non-variable bindings /// Tests that we do not lint for non-variable bindings
fn non_variables() { fn non_variables() {
_fn_test(); _fn_test();
let _s = _StructTest; let _s = _StructTest;

View file

@ -118,7 +118,7 @@ fn main() {
// regression test (#360) // regression test (#360)
// this should not panic // this should not panic
// it's okay if further iterations of the lint // it's ok if further iterations of the lint
// cause this function to trigger it // cause this function to trigger it
fn no_panic<T>(slice: &[T]) { fn no_panic<T>(slice: &[T]) {
let mut iter = slice.iter(); let mut iter = slice.iter();