diff --git a/.cargo/config b/.cargo/config index 7cb41d979a6a..b4bc4418f1e4 100644 --- a/.cargo/config +++ b/.cargo/config @@ -1,2 +1,5 @@ [alias] uitest = "test --test compile-test" + +[build] +rustflags = ["-Zunstable-options"] diff --git a/.github/PULL_REQUEST_TEMPLATE b/.github/PULL_REQUEST_TEMPLATE new file mode 100644 index 000000000000..5567b84b3f5a --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE @@ -0,0 +1,28 @@ + + +changelog: none diff --git a/CHANGELOG.md b/CHANGELOG.md index 620e03b07056..7188e6f93241 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1015,6 +1015,7 @@ All notable changes to this project will be documented in this file. [`panic_params`]: https://rust-lang.github.io/rust-clippy/master/index.html#panic_params [`panicking_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#panicking_unwrap [`partialeq_ne_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#partialeq_ne_impl +[`path_buf_push_overwrite`]: https://rust-lang.github.io/rust-clippy/master/index.html#path_buf_push_overwrite [`possible_missing_comma`]: https://rust-lang.github.io/rust-clippy/master/index.html#possible_missing_comma [`precedence`]: https://rust-lang.github.io/rust-clippy/master/index.html#precedence [`print_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#print_literal diff --git a/Cargo.toml b/Cargo.toml index e41440acc20e..eb97707e667a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,7 +46,7 @@ rustc_tools_util = { version = "0.1.1", path = "rustc_tools_util"} [dev-dependencies] cargo_metadata = "0.7.1" -compiletest_rs = { version = "0.3.21", features = ["tmp"] } +compiletest_rs = { version = "0.3.22", features = ["tmp"] } lazy_static = "1.0" serde_derive = "1.0" clippy-mini-macro-test = { version = "0.2", path = "mini-macro" } diff --git a/README.md b/README.md index 149520639331..9ca5761a2ba4 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 298 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +[There are 299 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_dev/rust-toolchain b/clippy_dev/rust-toolchain deleted file mode 100644 index 2bf5ad0447d3..000000000000 --- a/clippy_dev/rust-toolchain +++ /dev/null @@ -1 +0,0 @@ -stable diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index 31b0a98c1ab7..392388ffd8a1 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -1,5 +1,3 @@ -#![allow(clippy::default_hash_types)] - use itertools::Itertools; use lazy_static::lazy_static; use regex::Regex; diff --git a/clippy_lints/src/approx_const.rs b/clippy_lints/src/approx_const.rs index fa586ad45c23..62650b5cbb78 100644 --- a/clippy_lints/src/approx_const.rs +++ b/clippy_lints/src/approx_const.rs @@ -1,7 +1,7 @@ use crate::utils::span_lint; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use std::f64::consts as f64; use syntax::ast::{FloatTy, Lit, LitKind}; use syntax::symbol; @@ -53,20 +53,9 @@ const KNOWN_CONSTS: &[(f64, &str, usize)] = &[ (f64::SQRT_2, "SQRT_2", 5), ]; -#[derive(Copy, Clone)] -pub struct Pass; +declare_lint_pass!(ApproxConstant => [APPROX_CONSTANT]); -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(APPROX_CONSTANT) - } - - fn name(&self) -> &'static str { - "ApproxConstant" - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ApproxConstant { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { if let ExprKind::Lit(lit) = &e.node { check_lit(cx, lit, e); diff --git a/clippy_lints/src/arithmetic.rs b/clippy_lints/src/arithmetic.rs index 416ec656e12a..d94cd668bddc 100644 --- a/clippy_lints/src/arithmetic.rs +++ b/clippy_lints/src/arithmetic.rs @@ -2,7 +2,7 @@ use crate::consts::constant_simple; use crate::utils::span_lint; use rustc::hir; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_tool_lint, impl_lint_pass}; use syntax::source_map::Span; declare_clippy_lint! { @@ -48,15 +48,7 @@ pub struct Arithmetic { const_span: Option, } -impl LintPass for Arithmetic { - fn get_lints(&self) -> LintArray { - lint_array!(INTEGER_ARITHMETIC, FLOAT_ARITHMETIC) - } - - fn name(&self) -> &'static str { - "Arithmetic" - } -} +impl_lint_pass!(Arithmetic => [INTEGER_ARITHMETIC, FLOAT_ARITHMETIC]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Arithmetic { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) { diff --git a/clippy_lints/src/assertions_on_constants.rs b/clippy_lints/src/assertions_on_constants.rs index 9e2a8c451ee1..36ed835e2581 100644 --- a/clippy_lints/src/assertions_on_constants.rs +++ b/clippy_lints/src/assertions_on_constants.rs @@ -1,10 +1,10 @@ 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 rustc::{declare_lint_pass, declare_tool_lint}; +use syntax_pos::Span; use crate::consts::{constant, Constant}; -use crate::syntax::ast::LitKind; use crate::utils::{in_macro, is_direct_expn_of, span_help_and_lint}; declare_clippy_lint! { @@ -29,55 +29,44 @@ declare_clippy_lint! { "`assert!(true)` / `assert!(false)` will be optimized out by the compiler, and should probably be replaced by a `panic!()` or `unreachable!()`" } -pub struct AssertionsOnConstants; - -impl LintPass for AssertionsOnConstants { - fn get_lints(&self) -> LintArray { - lint_array![ASSERTIONS_ON_CONSTANTS] - } - - fn name(&self) -> &'static str { - "AssertionsOnConstants" - } -} +declare_lint_pass!(AssertionsOnConstants => [ASSERTIONS_ON_CONSTANTS]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssertionsOnConstants { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { + let mut is_debug_assert = false; + let debug_assert_not_in_macro = |span: Span| { + is_debug_assert = true; + // Check that `debug_assert!` itself is not inside a macro + !in_macro(span) + }; if_chain! { if let Some(assert_span) = is_direct_expn_of(e.span, "assert"); if !in_macro(assert_span) - || is_direct_expn_of(assert_span, "debug_assert").map_or(false, |span| !in_macro(span)); + || is_direct_expn_of(assert_span, "debug_assert") + .map_or(false, debug_assert_not_in_macro); if let ExprKind::Unary(_, ref lit) = e.node; + if let Some(bool_const) = constant(cx, cx.tables, lit); then { - if let ExprKind::Lit(ref inner) = lit.node { - match inner.node { - LitKind::Bool(true) => { - span_help_and_lint(cx, ASSERTIONS_ON_CONSTANTS, e.span, - "assert!(true) will be optimized out by the compiler", - "remove it"); - }, - LitKind::Bool(false) => { - span_help_and_lint( - cx, ASSERTIONS_ON_CONSTANTS, e.span, - "assert!(false) should probably be replaced", - "use panic!() or unreachable!()"); - }, - _ => (), - } - } else if let Some(bool_const) = constant(cx, cx.tables, lit) { - match bool_const.0 { - Constant::Bool(true) => { - span_help_and_lint(cx, ASSERTIONS_ON_CONSTANTS, e.span, - "assert!(const: true) will be optimized out by the compiler", - "remove it"); - }, - Constant::Bool(false) => { - span_help_and_lint(cx, ASSERTIONS_ON_CONSTANTS, e.span, - "assert!(const: false) should probably be replaced", - "use panic!() or unreachable!()"); - }, - _ => (), - } + match bool_const.0 { + Constant::Bool(true) => { + span_help_and_lint( + cx, + ASSERTIONS_ON_CONSTANTS, + e.span, + "`assert!(true)` will be optimized out by the compiler", + "remove it" + ); + }, + Constant::Bool(false) if !is_debug_assert => { + span_help_and_lint( + cx, + ASSERTIONS_ON_CONSTANTS, + e.span, + "`assert!(false)` should probably be replaced", + "use `panic!()` or `unreachable!()`" + ); + }, + _ => (), } } } diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index a39685f85ff8..98020303d37e 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -2,7 +2,7 @@ use if_chain::if_chain; use rustc::hir; use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; use crate::utils::{ @@ -53,18 +53,7 @@ declare_clippy_lint! { "having a variable on both sides of an assign op" } -#[derive(Copy, Clone, Default)] -pub struct AssignOps; - -impl LintPass for AssignOps { - fn get_lints(&self) -> LintArray { - lint_array!(ASSIGN_OP_PATTERN, MISREFACTORED_ASSIGN_OP) - } - - fn name(&self) -> &'static str { - "AssignOps" - } -} +declare_lint_pass!(AssignOps => [ASSIGN_OP_PATTERN, MISREFACTORED_ASSIGN_OP]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { #[allow(clippy::too_many_lines)] diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 52b3fc7f3449..3f62a02b4573 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -2,8 +2,8 @@ use crate::reexport::*; use crate::utils::{ - in_macro, last_line_of_span, match_def_path, paths, snippet_opt, span_lint, span_lint_and_sugg, span_lint_and_then, - without_block_comments, + in_macro, is_present_in_source, last_line_of_span, paths, snippet_opt, span_lint, span_lint_and_sugg, + span_lint_and_then, without_block_comments, }; use if_chain::if_chain; use rustc::hir::*; @@ -11,8 +11,8 @@ use rustc::lint::{ in_external_macro, CheckLintNameResult, EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintArray, LintContext, LintPass, }; -use rustc::ty::{self, TyCtxt}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::ty; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; use semver::Version; use syntax::ast::{AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem}; @@ -187,26 +187,15 @@ declare_clippy_lint! { "usage of `cfg_attr(rustfmt)` instead of `tool_attributes`" } -#[derive(Copy, Clone)] -pub struct AttrPass; +declare_lint_pass!(Attributes => [ + INLINE_ALWAYS, + DEPRECATED_SEMVER, + USELESS_ATTRIBUTE, + EMPTY_LINE_AFTER_OUTER_ATTR, + UNKNOWN_CLIPPY_LINTS, +]); -impl LintPass for AttrPass { - fn get_lints(&self) -> LintArray { - lint_array!( - INLINE_ALWAYS, - DEPRECATED_SEMVER, - USELESS_ATTRIBUTE, - EMPTY_LINE_AFTER_OUTER_ATTR, - UNKNOWN_CLIPPY_LINTS, - ) - } - - fn name(&self) -> &'static str { - "Attributes" - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Attributes { fn check_attribute(&mut self, cx: &LateContext<'a, 'tcx>, attr: &'tcx Attribute) { if let Some(items) = &attr.meta_item_list() { if let Some(ident) = attr.ident() { @@ -234,7 +223,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass { } fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { - if is_relevant_item(cx.tcx, item) { + if is_relevant_item(cx, item) { check_attrs(cx, item.span, item.ident.name, &item.attrs) } match item.node { @@ -302,13 +291,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass { } fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx ImplItem) { - if is_relevant_impl(cx.tcx, item) { + if is_relevant_impl(cx, item) { check_attrs(cx, item.span, item.ident.name, &item.attrs) } } fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem) { - if is_relevant_trait(cx.tcx, item) { + if is_relevant_trait(cx, item) { check_attrs(cx, item.span, item.ident.name, &item.attrs) } } @@ -361,52 +350,52 @@ fn check_clippy_lint_names(cx: &LateContext<'_, '_>, items: &[NestedMetaItem]) { } } -fn is_relevant_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item: &Item) -> bool { +fn is_relevant_item(cx: &LateContext<'_, '_>, item: &Item) -> bool { if let ItemKind::Fn(_, _, _, eid) = item.node { - is_relevant_expr(tcx, tcx.body_tables(eid), &tcx.hir().body(eid).value) + is_relevant_expr(cx, cx.tcx.body_tables(eid), &cx.tcx.hir().body(eid).value) } else { true } } -fn is_relevant_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item: &ImplItem) -> bool { +fn is_relevant_impl(cx: &LateContext<'_, '_>, item: &ImplItem) -> bool { match item.node { - ImplItemKind::Method(_, eid) => is_relevant_expr(tcx, tcx.body_tables(eid), &tcx.hir().body(eid).value), + ImplItemKind::Method(_, eid) => is_relevant_expr(cx, cx.tcx.body_tables(eid), &cx.tcx.hir().body(eid).value), _ => false, } } -fn is_relevant_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item: &TraitItem) -> bool { +fn is_relevant_trait(cx: &LateContext<'_, '_>, item: &TraitItem) -> bool { match item.node { TraitItemKind::Method(_, TraitMethod::Required(_)) => true, TraitItemKind::Method(_, TraitMethod::Provided(eid)) => { - is_relevant_expr(tcx, tcx.body_tables(eid), &tcx.hir().body(eid).value) + is_relevant_expr(cx, cx.tcx.body_tables(eid), &cx.tcx.hir().body(eid).value) }, _ => false, } } -fn is_relevant_block<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, tables: &ty::TypeckTables<'_>, block: &Block) -> bool { +fn is_relevant_block(cx: &LateContext<'_, '_>, tables: &ty::TypeckTables<'_>, block: &Block) -> bool { if let Some(stmt) = block.stmts.first() { match &stmt.node { StmtKind::Local(_) => true, - StmtKind::Expr(expr) | StmtKind::Semi(expr) => is_relevant_expr(tcx, tables, expr), + StmtKind::Expr(expr) | StmtKind::Semi(expr) => is_relevant_expr(cx, tables, expr), _ => false, } } else { - block.expr.as_ref().map_or(false, |e| is_relevant_expr(tcx, tables, e)) + block.expr.as_ref().map_or(false, |e| is_relevant_expr(cx, tables, e)) } } -fn is_relevant_expr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, tables: &ty::TypeckTables<'_>, expr: &Expr) -> bool { +fn is_relevant_expr(cx: &LateContext<'_, '_>, tables: &ty::TypeckTables<'_>, expr: &Expr) -> bool { match &expr.node { - ExprKind::Block(block, _) => is_relevant_block(tcx, tables, block), - ExprKind::Ret(Some(e)) => is_relevant_expr(tcx, tables, e), + ExprKind::Block(block, _) => is_relevant_block(cx, tables, block), + ExprKind::Ret(Some(e)) => is_relevant_expr(cx, tables, e), ExprKind::Ret(None) | ExprKind::Break(_, None) => false, ExprKind::Call(path_expr, _) => { if let ExprKind::Path(qpath) = &path_expr.node { if let Some(fun_id) = tables.qpath_def(qpath, path_expr.hir_id).opt_def_id() { - !match_def_path(tcx, fun_id, &paths::BEGIN_PANIC) + !cx.match_def_path(fun_id, &paths::BEGIN_PANIC) } else { true } @@ -492,34 +481,9 @@ fn is_word(nmi: &NestedMetaItem, expected: &str) -> bool { } } -// If the snippet is empty, it's an attribute that was inserted during macro -// expansion and we want to ignore those, because they could come from external -// sources that the user has no control over. -// For some reason these attributes don't have any expansion info on them, so -// we have to check it this way until there is a better way. -fn is_present_in_source(cx: &LateContext<'_, '_>, span: Span) -> bool { - if let Some(snippet) = snippet_opt(cx, span) { - if snippet.is_empty() { - return false; - } - } - true -} - -#[derive(Copy, Clone)] -pub struct CfgAttrPass; - -impl LintPass for CfgAttrPass { - fn get_lints(&self) -> LintArray { - lint_array!(DEPRECATED_CFG_ATTR,) - } - - fn name(&self) -> &'static str { - "DeprecatedCfgAttribute" - } -} +declare_lint_pass!(DeprecatedCfgAttribute => [DEPRECATED_CFG_ATTR]); -impl EarlyLintPass for CfgAttrPass { +impl EarlyLintPass for DeprecatedCfgAttribute { fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) { if_chain! { // check cfg_attr diff --git a/clippy_lints/src/bit_mask.rs b/clippy_lints/src/bit_mask.rs index 76314a610b16..71075500528e 100644 --- a/clippy_lints/src/bit_mask.rs +++ b/clippy_lints/src/bit_mask.rs @@ -4,7 +4,7 @@ use crate::utils::{span_lint, span_lint_and_then}; use if_chain::if_chain; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_tool_lint, impl_lint_pass}; use rustc_errors::Applicability; use syntax::ast::LitKind; use syntax::source_map::Span; @@ -107,14 +107,7 @@ impl BitMask { } } -impl LintPass for BitMask { - fn get_lints(&self) -> LintArray { - lint_array!(BAD_BIT_MASK, INEFFECTIVE_BIT_MASK, VERBOSE_BIT_MASK) - } - fn name(&self) -> &'static str { - "BitMask" - } -} +impl_lint_pass!(BitMask => [BAD_BIT_MASK, INEFFECTIVE_BIT_MASK, VERBOSE_BIT_MASK]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BitMask { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { diff --git a/clippy_lints/src/blacklisted_name.rs b/clippy_lints/src/blacklisted_name.rs index c1ee4d528854..33463df14529 100644 --- a/clippy_lints/src/blacklisted_name.rs +++ b/clippy_lints/src/blacklisted_name.rs @@ -1,7 +1,7 @@ use crate::utils::span_lint; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_tool_lint, impl_lint_pass}; use rustc_data_structures::fx::FxHashSet; declare_clippy_lint! { @@ -23,26 +23,19 @@ declare_clippy_lint! { } #[derive(Clone, Debug)] -pub struct BlackListedName { +pub struct BlacklistedName { blacklist: FxHashSet, } -impl BlackListedName { +impl BlacklistedName { pub fn new(blacklist: FxHashSet) -> Self { Self { blacklist } } } -impl LintPass for BlackListedName { - fn get_lints(&self) -> LintArray { - lint_array!(BLACKLISTED_NAME) - } - fn name(&self) -> &'static str { - "BlacklistedName" - } -} +impl_lint_pass!(BlacklistedName => [BLACKLISTED_NAME]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlackListedName { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlacklistedName { fn check_pat(&mut self, cx: &LateContext<'a, 'tcx>, pat: &'tcx Pat) { if let PatKind::Binding(.., ident, _) = pat.node { if self.blacklist.contains(&ident.name.to_string()) { diff --git a/clippy_lints/src/block_in_if_condition.rs b/clippy_lints/src/block_in_if_condition.rs index f16631a5eff6..1f20f5c41fcc 100644 --- a/clippy_lints/src/block_in_if_condition.rs +++ b/clippy_lints/src/block_in_if_condition.rs @@ -3,7 +3,7 @@ use matches::matches; use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { /// **What it does:** Checks for `if` conditions that use blocks to contain an @@ -42,18 +42,7 @@ declare_clippy_lint! { "complex blocks in conditions, e.g., `if { let x = true; x } ...`" } -#[derive(Copy, Clone)] -pub struct BlockInIfCondition; - -impl LintPass for BlockInIfCondition { - fn get_lints(&self) -> LintArray { - lint_array!(BLOCK_IN_IF_CONDITION_EXPR, BLOCK_IN_IF_CONDITION_STMT) - } - - fn name(&self) -> &'static str { - "BlockInIfCondition" - } -} +declare_lint_pass!(BlockInIfCondition => [BLOCK_IN_IF_CONDITION_EXPR, BLOCK_IN_IF_CONDITION_STMT]); struct ExVisitor<'a, 'tcx: 'a> { found_block: Option<&'tcx Expr>, diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index f7e0157746f4..779cb3cf90f8 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -4,7 +4,7 @@ use crate::utils::{ use rustc::hir::intravisit::*; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_data_structures::thin_vec::ThinVec; use rustc_errors::Applicability; use syntax::ast::LitKind; @@ -51,18 +51,7 @@ declare_clippy_lint! { // For each pairs, both orders are considered. const METHODS_WITH_NEGATION: [(&str, &str); 2] = [("is_some", "is_none"), ("is_err", "is_ok")]; -#[derive(Copy, Clone)] -pub struct NonminimalBool; - -impl LintPass for NonminimalBool { - fn get_lints(&self) -> LintArray { - lint_array!(NONMINIMAL_BOOL, LOGIC_BUG) - } - - fn name(&self) -> &'static str { - "NonminimalBool" - } -} +declare_lint_pass!(NonminimalBool => [NONMINIMAL_BOOL, LOGIC_BUG]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonminimalBool { fn check_fn( diff --git a/clippy_lints/src/bytecount.rs b/clippy_lints/src/bytecount.rs index 9fd82ae5946b..5716927be03e 100644 --- a/clippy_lints/src/bytecount.rs +++ b/clippy_lints/src/bytecount.rs @@ -6,7 +6,7 @@ use if_chain::if_chain; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::ty; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; use syntax::ast::{Name, UintTy}; @@ -31,18 +31,7 @@ declare_clippy_lint! { "use of naive `.filter(|&x| x == y).count()` to count byte values" } -#[derive(Copy, Clone)] -pub struct ByteCount; - -impl LintPass for ByteCount { - fn get_lints(&self) -> LintArray { - lint_array!(NAIVE_BYTECOUNT) - } - - fn name(&self) -> &'static str { - "ByteCount" - } -} +declare_lint_pass!(ByteCount => [NAIVE_BYTECOUNT]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ByteCount { fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &Expr) { @@ -86,7 +75,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ByteCount { } else { &filter_args[0] }; - let mut applicability = Applicability::MachineApplicable; + let mut applicability = Applicability::MaybeIncorrect; span_lint_and_sugg( cx, NAIVE_BYTECOUNT, diff --git a/clippy_lints/src/cargo_common_metadata.rs b/clippy_lints/src/cargo_common_metadata.rs index 57bdce4cf3a9..23532c4b0474 100644 --- a/clippy_lints/src/cargo_common_metadata.rs +++ b/clippy_lints/src/cargo_common_metadata.rs @@ -2,7 +2,7 @@ use crate::utils::span_lint; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use syntax::{ast::*, source_map::DUMMY_SP}; use cargo_metadata; @@ -56,19 +56,9 @@ fn is_empty_vec(value: &[String]) -> bool { value.iter().all(std::string::String::is_empty) } -pub struct Pass; +declare_lint_pass!(CargoCommonMetadata => [CARGO_COMMON_METADATA]); -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(CARGO_COMMON_METADATA) - } - - fn name(&self) -> &'static str { - "CargoCommonMetadata" - } -} - -impl EarlyLintPass for Pass { +impl EarlyLintPass for CargoCommonMetadata { fn check_crate(&mut self, cx: &EarlyContext<'_>, _: &Crate) { let metadata = if let Ok(metadata) = cargo_metadata::MetadataCommand::new().no_deps().exec() { metadata diff --git a/clippy_lints/src/cognitive_complexity.rs b/clippy_lints/src/cognitive_complexity.rs index d44784843e73..41c62a660b91 100644 --- a/clippy_lints/src/cognitive_complexity.rs +++ b/clippy_lints/src/cognitive_complexity.rs @@ -1,15 +1,13 @@ //! calculate cognitive complexity and warn about overly complex functions -use rustc::cfg::CFG; -use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; -use rustc::hir::*; -use rustc::lint::{LateContext, LateLintPass, LintArray, LintContext, LintPass}; -use rustc::ty; -use rustc::{declare_tool_lint, lint_array}; +use rustc::lint::{EarlyContext, EarlyLintPass}; +use rustc::lint::{LintArray, LintContext, LintPass}; +use rustc::{declare_tool_lint, impl_lint_pass}; use syntax::ast::Attribute; -use syntax::source_map::Span; +use syntax::ast::*; +use syntax::visit::{walk_expr, Visitor}; -use crate::utils::{in_macro, is_allowed, match_type, paths, span_help_and_lint, LimitStack}; +use crate::utils::{span_help_and_lint, LimitStack}; declare_clippy_lint! { /// **What it does:** Checks for methods with high cognitive complexity. @@ -20,7 +18,9 @@ declare_clippy_lint! { /// **Known problems:** Sometimes it's hard to find a way to reduce the /// complexity. /// - /// **Example:** No. You'll see it when you get the warning. + /// **Example:** Sorry. Examples are too big and varied to put in here. For a + /// complete explanation of the analysis being made though, you can read this paper: + /// https://www.sonarsource.com/docs/CognitiveComplexity.pdf pub COGNITIVE_COMPLEXITY, complexity, "functions that should be split up into multiple functions" @@ -28,210 +28,475 @@ declare_clippy_lint! { pub struct CognitiveComplexity { limit: LimitStack, + current_enclosing_function: Option, } impl CognitiveComplexity { pub fn new(limit: u64) -> Self { Self { limit: LimitStack::new(limit), + current_enclosing_function: None, } } } -impl LintPass for CognitiveComplexity { - fn get_lints(&self) -> LintArray { - lint_array!(COGNITIVE_COMPLEXITY) +impl_lint_pass!(CognitiveComplexity => [COGNITIVE_COMPLEXITY]); + +impl EarlyLintPass for CognitiveComplexity { + fn check_item_post(&mut self, _: &EarlyContext<'_>, item: &Item) { + // After processing the inner AST of a function, we unrecord its + // id, so that other functions can now be recognized and processed. + if let Some(fn_id) = self.current_enclosing_function { + if item.id == fn_id { + self.current_enclosing_function = None; + } + } + } + + fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { + if let ItemKind::Fn(_, _, _, fn_block) = &item.node { + // Before scoring a function, we check that it's not + // an inner function. If it was, then we'd be scoring it + // twice: once for its parent and once for itself. + if let None = self.current_enclosing_function { + // Now that we've entered a function, we record it + // as the current enclosing one. No functions inside it + // will ever be scored now. + self.current_enclosing_function = Some(item.id); + + // If the function being explored is marked as "test", + // then we skip it. + if item.attrs.iter().any(|a| a.check_name("test")) { + return; + } + + let mut helper = CoCHelper::new(); + + helper.visit_block(&fn_block); + + let fn_score = helper.score; + let score_limit = self.limit.limit(); + + if fn_score > score_limit { + span_help_and_lint( + cx, + COGNITIVE_COMPLEXITY, + item.span, + &format!("the function has a cognitive complexity of {}", fn_score), + "you could split it up into multiple smaller functions", + ); + } + } + } } - fn name(&self) -> &'static str { - "CognitiveComplexity" + fn enter_lint_attrs(&mut self, cx: &EarlyContext<'_>, attrs: &[Attribute]) { + self.limit.push_attrs(cx.sess(), attrs, "cognitive_complexity"); + } + fn exit_lint_attrs(&mut self, cx: &EarlyContext<'_>, attrs: &[Attribute]) { + self.limit.pop_attrs(cx.sess(), attrs, "cognitive_complexity"); } } -impl CognitiveComplexity { - fn check<'a, 'tcx: 'a>(&mut self, cx: &'a LateContext<'a, 'tcx>, body: &'tcx Body, span: Span) { - if in_macro(span) { - return; - } +/// Helps keep track of the Cognitive Complexity Score +/// of a function being analyzed. +struct CoCHelper { + /// Current Nesting value + current_nesting: u64, + /// Current Cognitive Complexity score + score: u64, + /// Current Nesting of Binary Logical Operations + /// (used for proper score calculation) + logical_binop_nesting: u64, +} - let cfg = CFG::new(cx.tcx, body); - let expr = &body.value; - let n = cfg.graph.len_nodes() as u64; - let e = cfg.graph.len_edges() as u64; - if e + 2 < n { - // the function has unreachable code, other lints should catch this - return; - } - let cc = e + 2 - n; - let mut helper = CCHelper { - match_arms: 0, - divergence: 0, - short_circuits: 0, - returns: 0, - cx, - }; - helper.visit_expr(expr); - let CCHelper { - match_arms, - divergence, - short_circuits, - returns, - .. - } = helper; - let ret_ty = cx.tables.node_type(expr.hir_id); - let ret_adjust = if match_type(cx, ret_ty, &paths::RESULT) { - returns - } else { - returns / 2 - }; - - if cc + divergence < match_arms + short_circuits { - report_cc_bug( - cx, - cc, - match_arms, - divergence, - short_circuits, - ret_adjust, - span, - body.id().hir_id, - ); - } else { - let mut rust_cc = cc + divergence - match_arms - short_circuits; - // prevent degenerate cases where unreachable code contains `return` statements - if rust_cc >= ret_adjust { - rust_cc -= ret_adjust; - } - if rust_cc > self.limit.limit() { - span_help_and_lint( - cx, - COGNITIVE_COMPLEXITY, - span, - &format!("the function has a cognitive complexity of {}", rust_cc), - "you could split it up into multiple smaller functions", - ); - } +enum ComplexityLevel { + /// Almost no individual score (Paren, Assign, AssignOp) + Low, + /// Most common score (If, Return, Yield) + Normal, + // FIXME: delete or populate this case. + /// High score (no cases yet?) + High, + /// Custom score (a catch-all for other cases) + Custom(u64), +} + +impl ComplexityLevel { + fn get_score(&self) -> u64 { + match self { + ComplexityLevel::Low => 2, + ComplexityLevel::Normal => 10, + ComplexityLevel::High => 50, + ComplexityLevel::Custom(score) => *score, } } } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CognitiveComplexity { - fn check_fn( - &mut self, - cx: &LateContext<'a, 'tcx>, - _: intravisit::FnKind<'tcx>, - _: &'tcx FnDecl, - body: &'tcx Body, - span: Span, - hir_id: HirId, - ) { - let def_id = cx.tcx.hir().local_def_id_from_hir_id(hir_id); - if !cx.tcx.has_attr(def_id, "test") { - self.check(cx, body, span); +impl CoCHelper { + /// Create a clean CoCHelper + fn new() -> CoCHelper { + CoCHelper { + current_nesting: 0, + score: 0, + logical_binop_nesting: 0, } } - fn enter_lint_attrs(&mut self, cx: &LateContext<'a, 'tcx>, attrs: &'tcx [Attribute]) { - self.limit.push_attrs(cx.sess(), attrs, "cognitive_complexity"); + /// Increment the nesting level by one + fn push_nesting(&mut self) { + self.current_nesting += 1; } - fn exit_lint_attrs(&mut self, cx: &LateContext<'a, 'tcx>, attrs: &'tcx [Attribute]) { - self.limit.pop_attrs(cx.sess(), attrs, "cognitive_complexity"); + + /// Decrement the nesting level by one + fn pop_nesting(&mut self) { + assert!(self.current_nesting > 0); + self.current_nesting -= 1; + } + + /// Mark a determined amount of score + fn add_to_score(&mut self, amount: u64) { + self.score += amount; + } + + /// Mark score for a Nesting-Dependent Structure + fn score_nd_structure(&mut self, level: ComplexityLevel) { + self.add_to_score(self.current_nesting * level.get_score()); + self.score_ni_structure(level); } -} -struct CCHelper<'a, 'tcx: 'a> { - match_arms: u64, - divergence: u64, - returns: u64, - short_circuits: u64, // && and || - cx: &'a LateContext<'a, 'tcx>, + /// Mark score for a Nesting-Independent Structure + fn score_ni_structure(&mut self, level: ComplexityLevel) { + self.add_to_score(level.get_score()); + } + + /// Let the helper know that we've entered a Binary Logical Operation + fn enter_logical_binop(&mut self) { + // We score once every time we enter a *new* + // binary logical operation. + // That way, the score for chains is + // `1 + (number of operator changes in the chain)` + if self.logical_binop_nesting == 0 { + self.score_ni_structure(ComplexityLevel::Normal); + } + self.logical_binop_nesting += 1; + } + + /// Let the helper know that we've exited a Binary Logical Operation + fn exit_logical_binop(&mut self) { + self.logical_binop_nesting -= 1; + } } -impl<'a, 'tcx> Visitor<'tcx> for CCHelper<'a, 'tcx> { - fn visit_expr(&mut self, e: &'tcx Expr) { - match e.node { - ExprKind::Match(_, ref arms, _) => { - walk_expr(self, e); - let arms_n: u64 = arms.iter().map(|arm| arm.pats.len() as u64).sum(); - if arms_n > 1 { - self.match_arms += arms_n - 2; - } +impl<'ast> Visitor<'ast> for CoCHelper { + /* + # Implemented here: + + ## Nesting Structures + IMPORTANT: ExprKind::Block(..) + already covers all cases. + ## (Nesting-Dependent) Increments + if + match + for, while, loop + ## (Nesting-Independent) Increments + break, continue + Sequences of binary logical operators + Function calls + Macro calls + */ + + fn visit_expr(&mut self, ex: &'ast Expr) { + match ex.node { + // Nesting-Increasing (the one and only) + ExprKind::Block(..) => { + self.push_nesting(); + walk_expr(self, ex); + self.pop_nesting(); + }, + + ExprKind::Closure(.., _) + | ExprKind::IfLet(..) + | ExprKind::Lit(..) + | ExprKind::Try(..) => { + // "If Let" and "Try" are free of own increment. + // This is because they are language constructs + // specifically designed to save on complexity. + walk_expr(self, ex); + }, + + // FIXME (FAR FUTURE): make a separate, documented case, for recursive calls, + // such that it's treated differently from function or method calls. + ExprKind::Call(..) | ExprKind::MethodCall(..) => { + self.score_ni_structure(ComplexityLevel::Normal); + walk_expr(self, ex); + }, + + // Nesting-Dependent + ExprKind::If(..) + | ExprKind::Match(..) + | ExprKind::ForLoop(..) + | ExprKind::While(..) + | ExprKind::Loop(..) + | ExprKind::WhileLet(..) => { + // (For the IF-Case) + // Important: this pays for one "if" and one "else". + // Every "if" in an "else if" comes here again to pay + // for itself and its subsequent else. + self.score_nd_structure(ComplexityLevel::Normal); + walk_expr(self, ex); + }, + + // Nesting-Independent + ExprKind::Mac(ref mac) => { + self.visit_mac(mac); + }, + + // Nesting-Independent + ExprKind::Continue(_) => { + self.score_ni_structure(ComplexityLevel::Normal); }, - ExprKind::Call(ref callee, _) => { - walk_expr(self, e); - let ty = self.cx.tables.node_type(callee.hir_id); - match ty.sty { - ty::FnDef(..) | ty::FnPtr(_) => { - let sig = ty.fn_sig(self.cx.tcx); - if sig.skip_binder().output().sty == ty::Never { - self.divergence += 1; - } - }, - _ => (), + + // Nesting-Independent, + // Sometimes Nesting + ExprKind::Break(_, ref maybe_inner_ex) => { + self.score_ni_structure(ComplexityLevel::Normal); + if let Some(ref inner_ex) = maybe_inner_ex { + walk_expr(self, inner_ex); } }, - ExprKind::Closure(.., _) => (), - ExprKind::Binary(op, _, _) => { - walk_expr(self, e); - match op.node { - BinOpKind::And | BinOpKind::Or => self.short_circuits += 1, - _ => (), + + // (Nesting-Independent) When boolean operators change, we add 1 to the score. + ExprKind::Binary(binop, ref l_ex, ref r_ex) => { + // Here, we're either looking for the leftmost logical operator on the right side, + // or the rightmost logical operator on the left side. It looks like this: + // + // Let's say our Expr is `(a && b) || ((c ^ d) & e)`, and its AST: + // + // Or + // / \ + // / \ + // / \ + // Paren Paren + // | | + // And BitAnd + // / \ / \ + // a b / \ + // Paren e + // | + // Xor + // / \ + // c d + // + // Then, when we call `log_op_at(right_branch, At:LeftMostSide)`, + // We're looking for that Xor at the leftmost side of the right branch: + // Or + // / \ + // / \ + // / \ + // Paren Paren + // | | + // And BitAnd + // / \ / \ + // a b / \ + // Paren e + // | + // Xor <~ THIS ONE :D + // / \ + // c d + // + // Doing this, we can effectively mark a score whenever there is a change + // in the current chain of logical operators. + // + // So say for example, that we're scoring `a && b && c || d && e`. + // There are 2 changes in the operator chain in this expression, + // once at `c || d` (it changes from `&&` to `||`) and once at + // `d && e` (it changes from `||` to `&&`). + // + // In order for us to score this change, regardless of the shape of + // the AST, we need to be able to know which operator sits right + // next to the current one. If it's then a different operator, + // we know there is a change in the chain, and we can score it. + // + // But what about scoring it twice? Will we see the same change + // more than once? + // The answer is no: since ASTs are recursive, child operators + // can't see their parent operators. Given we're only scoring + // a change whenever the operators right next to the current one + // are different to it, AND in our subsequent calls the current + // operator will not be visible, it's effectively impossible + // to score this change in the chain more than once. + + /// A location in the AST. + enum At { + LeftMostSide, + RightMostSide, + } + + /// A logical operator + #[derive(PartialEq)] + enum LogOp { + LogAnd, // && + LogOr, // || + BitAnd, // & + BitOr, // | + BitXor, // ^ + None, // Other + } + + /// Translate from a binary operator to a logical operator + fn log_op_from_bin_op(bop_kind: BinOpKind) -> LogOp { + match bop_kind { + BinOpKind::And => LogOp::LogAnd, + BinOpKind::Or => LogOp::LogOr, + BinOpKind::BitAnd => LogOp::BitAnd, + BinOpKind::BitOr => LogOp::BitOr, + BinOpKind::BitXor => LogOp::BitXor, + _ => LogOp::None, + } + } + + /// Find the rightmost or leftmost logical operator inside of the given `Expr` + fn log_op_at(expr: &Expr, at: At) -> LogOp { + match &expr.node { + ExprKind::Binary(binop, ref left_side, ref right_side) => { + let current_operator = log_op_from_bin_op(binop.node); + + let next_operator = match at { + At::LeftMostSide => log_op_at(left_side, at), + At::RightMostSide => log_op_at(right_side, at), + }; + + match next_operator { + LogOp::None => current_operator, + _ => next_operator, + } + }, + ExprKind::Paren(expr) | ExprKind::Unary(_, expr) => log_op_at(&expr, at), + _ => LogOp::None, + } + } + + let current_log_op = log_op_from_bin_op(binop.node); + + let is_log_op = current_log_op != LogOp::None; + + if is_log_op { + // Here we separate the left and right branches, and go looking + // for the rightmost and leftmost logical operator in them, respectively + let op_at_left_side = log_op_at(l_ex, At::RightMostSide); + let op_at_right_side = log_op_at(r_ex, At::LeftMostSide); + + if op_at_left_side != LogOp::None && current_log_op != op_at_left_side { + self.score_ni_structure(ComplexityLevel::Normal); + } + + if op_at_right_side != LogOp::None && current_log_op != op_at_right_side { + self.score_ni_structure(ComplexityLevel::Normal); + } + + self.enter_logical_binop(); } + + walk_expr(self, ex); + + if is_log_op { + self.exit_logical_binop(); + } + }, + + /* + Low complexity cases + */ + + // (...) + // ExprKind::Paren(..) => {}, + + // # a += bar() + // ExprKind::AssignOp(..) => {}, + + // # a = foo() + // ExprKind::Assign(..) => {}, + + // # foo[2] + // ExprKind::Index(..) => {}, + + // # a.count, or b.0 + // ExprKind::Field(..) => {}, + + // # &a or &mut a + // ExprKind::AddrOf(..) => {}, + + // !a, *b + // ExprKind::Unary(..) => {}, + + /* + Medium complexity cases + */ + + // Return and Yield have the same cog. complexity + // ExprKind::Ret(..) => {}, + // ExprKind::Yield(..) => {}, + + // # foo as f32 + // ExprKind::Cast(..) => {}, + + // # Struct literal: Foo { (things) } + // ExprKind::Struct(..) => {}, + + // # (a, b, c) + // ExprKind::Tup(..) => {}, + + // # [a, b, c, d] + // ExprKind::Array(..) => {}, + + // # m..n + // ExprKind::Range(..) => {}, + + /* + ### Pending ones (FIXME) ### + */ + + // # [m; n] + // ExprKind::Repeat(..) => {}, + + // Haven't used these. Investigate further. + // ExprKind::TryBlock(..) => {}, + + // # Variable reference?? + // ExprKind::Path(..) => {}, + + // # (unstable) `box a` syntax + // ExprKind::Box(..) => {}, + + // # FIXME: what is this? + // ExprKind::ObsoleteInPlace(..) => {}, + + // What is Type Ascription?? + // ExprKind::Type(..) => {}, + + // Unstable, leave it for after the MVP. + // ExprKind::Async(..) => {}, + + // # asm!(), basically, inline assembly + // ExprKind::InlineAsm(..) => {}, + + // Ill formed expressions. + ExprKind::Err => { + panic!("Found an ExprKind::Err. Is this a compiler bug??"); + }, + + _ => { + walk_expr(self, ex); }, - ExprKind::Ret(_) => self.returns += 1, - _ => walk_expr(self, e), } } - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::None - } -} -#[cfg(feature = "debugging")] -#[allow(clippy::too_many_arguments)] -fn report_cc_bug( - _: &LateContext<'_, '_>, - cc: u64, - narms: u64, - div: u64, - shorts: u64, - returns: u64, - span: Span, - _: HirId, -) { - span_bug!( - span, - "Clippy encountered a bug calculating cognitive complexity: cc = {}, arms = {}, \ - div = {}, shorts = {}, returns = {}. Please file a bug report.", - cc, - narms, - div, - shorts, - returns - ); -} -#[cfg(not(feature = "debugging"))] -#[allow(clippy::too_many_arguments)] -fn report_cc_bug( - cx: &LateContext<'_, '_>, - cc: u64, - narms: u64, - div: u64, - shorts: u64, - returns: u64, - span: Span, - id: HirId, -) { - if !is_allowed(cx, COGNITIVE_COMPLEXITY, id) { - cx.sess().span_note_without_error( - span, - &format!( - "Clippy encountered a bug calculating cognitive complexity \ - (hide this message with `#[allow(cognitive_complexity)]`): \ - cc = {}, arms = {}, div = {}, shorts = {}, returns = {}. \ - Please file a bug report.", - cc, narms, div, shorts, returns - ), - ); + fn visit_mac(&mut self, _mac: &Mac) { + // We override this so that the compiler + // doesn't panic. See the original implementation + // of `visit_mac` at rustc's src/libsyntax/visit.rs + // to know what normally happens. + self.score_ni_structure(ComplexityLevel::Normal); } } diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs index 00e0787a927d..c1d39716083e 100644 --- a/clippy_lints/src/collapsible_if.rs +++ b/clippy_lints/src/collapsible_if.rs @@ -14,7 +14,7 @@ use if_chain::if_chain; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use syntax::ast; use crate::utils::sugg::Sugg; @@ -71,18 +71,7 @@ declare_clippy_lint! { "`if`s that can be collapsed (e.g., `if x { if y { ... } }` and `else { if x { ... } }`)" } -#[derive(Copy, Clone)] -pub struct CollapsibleIf; - -impl LintPass for CollapsibleIf { - fn get_lints(&self) -> LintArray { - lint_array!(COLLAPSIBLE_IF) - } - - fn name(&self) -> &'static str { - "CollapsibleIf" - } -} +declare_lint_pass!(CollapsibleIf => [COLLAPSIBLE_IF]); impl EarlyLintPass for CollapsibleIf { fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) { diff --git a/clippy_lints/src/const_static_lifetime.rs b/clippy_lints/src/const_static_lifetime.rs index 1e369044d246..50e1781d2cb5 100644 --- a/clippy_lints/src/const_static_lifetime.rs +++ b/clippy_lints/src/const_static_lifetime.rs @@ -1,6 +1,6 @@ use crate::utils::{in_macro, snippet, span_lint_and_then}; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; use syntax::ast::*; @@ -26,17 +26,7 @@ declare_clippy_lint! { "Using explicit `'static` lifetime for constants when elision rules would allow omitting them." } -pub struct StaticConst; - -impl LintPass for StaticConst { - fn get_lints(&self) -> LintArray { - lint_array!(CONST_STATIC_LIFETIME) - } - - fn name(&self) -> &'static str { - "StaticConst" - } -} +declare_lint_pass!(StaticConst => [CONST_STATIC_LIFETIME]); impl StaticConst { // Recursively visit types diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 4442d8a2d6bf..3aa826d8bed6 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -1,6 +1,6 @@ #![allow(clippy::float_cmp)] -use crate::utils::{clip, get_def_path, sext, unsext}; +use crate::utils::{clip, sext, unsext}; use if_chain::if_chain; use rustc::hir::def::Def; use rustc::hir::*; @@ -180,7 +180,7 @@ pub fn constant<'c, 'cc>( e: &Expr, ) -> Option<(Constant, bool)> { let mut cx = ConstEvalLateContext { - tcx: lcx.tcx, + lcx, tables, param_env: lcx.param_env, needed_resolution: false, @@ -199,11 +199,11 @@ pub fn constant_simple<'c, 'cc>( /// Creates a `ConstEvalLateContext` from the given `LateContext` and `TypeckTables`. pub fn constant_context<'c, 'cc>( - lcx: &LateContext<'c, 'cc>, + lcx: &'c LateContext<'c, 'cc>, tables: &'c ty::TypeckTables<'cc>, ) -> ConstEvalLateContext<'c, 'cc> { ConstEvalLateContext { - tcx: lcx.tcx, + lcx, tables, param_env: lcx.param_env, needed_resolution: false, @@ -212,7 +212,7 @@ pub fn constant_context<'c, 'cc>( } pub struct ConstEvalLateContext<'a, 'tcx: 'a> { - tcx: TyCtxt<'a, 'tcx, 'tcx>, + lcx: &'a LateContext<'a, 'tcx>, tables: &'a ty::TypeckTables<'tcx>, param_env: ty::ParamEnv<'tcx>, needed_resolution: bool, @@ -231,7 +231,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { ExprKind::Tup(ref tup) => self.multi(tup).map(Constant::Tuple), ExprKind::Repeat(ref value, _) => { let n = match self.tables.expr_ty(e).sty { - ty::Array(_, n) => n.assert_usize(self.tcx).expect("array length"), + ty::Array(_, n) => n.assert_usize(self.lcx.tcx).expect("array length"), _ => span_bug!(e.span, "typeck error"), }; self.expr(value).map(|v| Constant::Repeat(Box::new(v), n)) @@ -249,7 +249,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { if let ExprKind::Path(qpath) = &callee.node; let def = self.tables.qpath_def(qpath, callee.hir_id); if let Some(def_id) = def.opt_def_id(); - let def_path = get_def_path(self.tcx, def_id) + let def_path = self.lcx.get_def_path(def_id) .iter() .map(LocalInternedString::get) .collect::>(); @@ -283,8 +283,8 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { Int(value) => { let value = !value; match ty.sty { - ty::Int(ity) => Some(Int(unsext(self.tcx, value as i128, ity))), - ty::Uint(ity) => Some(Int(clip(self.tcx, value, ity))), + ty::Int(ity) => Some(Int(unsext(self.lcx.tcx, value as i128, ity))), + ty::Uint(ity) => Some(Int(clip(self.lcx.tcx, value, ity))), _ => None, } }, @@ -301,10 +301,10 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { _ => return None, }; // sign extend - let value = sext(self.tcx, value, ity); + let value = sext(self.lcx.tcx, value, ity); let value = value.checked_neg()?; // clear unused bits - Some(Int(unsext(self.tcx, value, ity))) + Some(Int(unsext(self.lcx.tcx, value, ity))) }, F32(f) => Some(F32(-f)), F64(f) => Some(F64(-f)), @@ -329,16 +329,16 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { let substs = if self.substs.is_empty() { substs } else { - substs.subst(self.tcx, self.substs) + substs.subst(self.lcx.tcx, self.substs) }; - let instance = Instance::resolve(self.tcx, self.param_env, def_id, substs)?; + let instance = Instance::resolve(self.lcx.tcx, self.param_env, def_id, substs)?; let gid = GlobalId { instance, promoted: None, }; - let result = self.tcx.const_eval(self.param_env.and(gid)).ok()?; - let ret = miri_to_const(self.tcx, &result); + let result = self.lcx.tcx.const_eval(self.param_env.and(gid)).ok()?; + let ret = miri_to_const(self.lcx.tcx, &result); if ret.is_some() { self.needed_resolution = true; } @@ -376,9 +376,9 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { match (l, r) { (Constant::Int(l), Some(Constant::Int(r))) => match self.tables.expr_ty(left).sty { ty::Int(ity) => { - let l = sext(self.tcx, l, ity); - let r = sext(self.tcx, r, ity); - let zext = |n: i128| Constant::Int(unsext(self.tcx, n, ity)); + let l = sext(self.lcx.tcx, l, ity); + let r = sext(self.lcx.tcx, r, ity); + let zext = |n: i128| Constant::Int(unsext(self.lcx.tcx, n, ity)); match op.node { BinOpKind::Add => l.checked_add(r).map(zext), BinOpKind::Sub => l.checked_sub(r).map(zext), diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index 39fc10258078..d1163e102790 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -3,7 +3,7 @@ use crate::utils::{SpanlessEq, SpanlessHash}; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::ty::Ty; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_data_structures::fx::FxHashMap; use smallvec::SmallVec; use std::collections::hash_map::Entry; @@ -103,18 +103,7 @@ declare_clippy_lint! { "`match` with identical arm bodies" } -#[derive(Copy, Clone, Debug)] -pub struct CopyAndPaste; - -impl LintPass for CopyAndPaste { - fn get_lints(&self) -> LintArray { - lint_array![IFS_SAME_COND, IF_SAME_THEN_ELSE, MATCH_SAME_ARMS] - } - - fn name(&self) -> &'static str { - "CopyAndPaste" - } -} +declare_lint_pass!(CopyAndPaste => [IFS_SAME_COND, IF_SAME_THEN_ELSE, MATCH_SAME_ARMS]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CopyAndPaste { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { diff --git a/clippy_lints/src/copy_iterator.rs b/clippy_lints/src/copy_iterator.rs index 5c8d6def210f..79e30f1a7d8a 100644 --- a/clippy_lints/src/copy_iterator.rs +++ b/clippy_lints/src/copy_iterator.rs @@ -1,7 +1,7 @@ use crate::utils::{is_copy, match_path, paths, span_note_and_lint}; use rustc::hir::{Item, ItemKind}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { /// **What it does:** Checks for types that implement `Copy` as well as @@ -29,17 +29,7 @@ declare_clippy_lint! { "implementing `Iterator` on a `Copy` type" } -pub struct CopyIterator; - -impl LintPass for CopyIterator { - fn get_lints(&self) -> LintArray { - lint_array![COPY_ITERATOR] - } - - fn name(&self) -> &'static str { - "CopyIterator" - } -} +declare_lint_pass!(CopyIterator => [COPY_ITERATOR]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CopyIterator { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { diff --git a/clippy_lints/src/dbg_macro.rs b/clippy_lints/src/dbg_macro.rs index 8b71123ca55b..c54bafae56a1 100644 --- a/clippy_lints/src/dbg_macro.rs +++ b/clippy_lints/src/dbg_macro.rs @@ -1,6 +1,6 @@ use crate::utils::{snippet_opt, span_help_and_lint, span_lint_and_sugg}; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; use syntax::ast; use syntax::source_map::Span; @@ -27,20 +27,9 @@ declare_clippy_lint! { "`dbg!` macro is intended as a debugging tool" } -#[derive(Copy, Clone, Debug)] -pub struct Pass; +declare_lint_pass!(DbgMacro => [DBG_MACRO]); -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(DBG_MACRO) - } - - fn name(&self) -> &'static str { - "DbgMacro" - } -} - -impl EarlyLintPass for Pass { +impl EarlyLintPass for DbgMacro { fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &ast::Mac) { if mac.node.path == "dbg" { if let Some(sugg) = tts_span(mac.node.tts.clone()).and_then(|span| snippet_opt(cx, span)) { diff --git a/clippy_lints/src/default_trait_access.rs b/clippy_lints/src/default_trait_access.rs index 247dff756099..3e3663d6d0ae 100644 --- a/clippy_lints/src/default_trait_access.rs +++ b/clippy_lints/src/default_trait_access.rs @@ -2,10 +2,10 @@ use if_chain::if_chain; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::ty; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; -use crate::utils::{any_parent_is_automatically_derived, match_def_path, paths, span_lint_and_sugg}; +use crate::utils::{any_parent_is_automatically_derived, paths, span_lint_and_sugg}; declare_clippy_lint! { /// **What it does:** Checks for literal calls to `Default::default()`. @@ -28,18 +28,7 @@ declare_clippy_lint! { "checks for literal calls to Default::default()" } -#[derive(Copy, Clone)] -pub struct DefaultTraitAccess; - -impl LintPass for DefaultTraitAccess { - fn get_lints(&self) -> LintArray { - lint_array!(DEFAULT_TRAIT_ACCESS) - } - - fn name(&self) -> &'static str { - "DefaultTraitAccess" - } -} +declare_lint_pass!(DefaultTraitAccess => [DEFAULT_TRAIT_ACCESS]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DefaultTraitAccess { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { @@ -48,7 +37,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DefaultTraitAccess { if !any_parent_is_automatically_derived(cx.tcx, expr.hir_id); if let ExprKind::Path(ref qpath) = path.node; if let Some(def_id) = cx.tables.qpath_def(qpath, path.hir_id).opt_def_id(); - if match_def_path(cx.tcx, def_id, &paths::DEFAULT_TRAIT_METHOD); + if cx.match_def_path(def_id, &paths::DEFAULT_TRAIT_METHOD); then { match qpath { QPath::Resolved(..) => { diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 2c77f8d37fac..bf2845af1336 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -4,7 +4,7 @@ use if_chain::if_chain; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::ty::{self, Ty}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use syntax::source_map::Span; declare_clippy_lint! { @@ -62,17 +62,7 @@ declare_clippy_lint! { "implementing `Clone` explicitly on `Copy` types" } -pub struct Derive; - -impl LintPass for Derive { - fn get_lints(&self) -> LintArray { - lint_array!(EXPL_IMPL_CLONE_ON_COPY, DERIVE_HASH_XOR_EQ) - } - - fn name(&self) -> &'static str { - "Derive" - } -} +declare_lint_pass!(Derive => [EXPL_IMPL_CLONE_ON_COPY, DERIVE_HASH_XOR_EQ]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Derive { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 413645a091ff..4ad6554a213c 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -2,7 +2,7 @@ use crate::utils::span_lint; use itertools::Itertools; use pulldown_cmark; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_tool_lint, impl_lint_pass}; use rustc_data_structures::fx::FxHashSet; use syntax::ast; use syntax::source_map::{BytePos, Span}; @@ -33,28 +33,21 @@ declare_clippy_lint! { "presence of `_`, `::` or camel-case outside backticks in documentation" } +#[allow(clippy::module_name_repetitions)] #[derive(Clone)] -pub struct Doc { +pub struct DocMarkdown { valid_idents: FxHashSet, } -impl Doc { +impl DocMarkdown { pub fn new(valid_idents: FxHashSet) -> Self { Self { valid_idents } } } -impl LintPass for Doc { - fn get_lints(&self) -> LintArray { - lint_array![DOC_MARKDOWN] - } - - fn name(&self) -> &'static str { - "DocMarkdown" - } -} +impl_lint_pass!(DocMarkdown => [DOC_MARKDOWN]); -impl EarlyLintPass for Doc { +impl EarlyLintPass for DocMarkdown { fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &ast::Crate) { check_attrs(cx, &self.valid_idents, &krate.attrs); } diff --git a/clippy_lints/src/double_comparison.rs b/clippy_lints/src/double_comparison.rs index be6124e45536..d64939d01298 100644 --- a/clippy_lints/src/double_comparison.rs +++ b/clippy_lints/src/double_comparison.rs @@ -2,7 +2,7 @@ use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; use syntax::source_map::Span; @@ -31,21 +31,11 @@ declare_clippy_lint! { "unnecessary double comparisons that can be simplified" } -pub struct Pass; +declare_lint_pass!(DoubleComparisons => [DOUBLE_COMPARISONS]); -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(DOUBLE_COMPARISONS) - } - - fn name(&self) -> &'static str { - "DoubleComparisons" - } -} - -impl<'a, 'tcx> Pass { +impl<'a, 'tcx> DoubleComparisons { #[allow(clippy::similar_names)] - fn check_binop(&self, cx: &LateContext<'a, 'tcx>, op: BinOpKind, lhs: &'tcx Expr, rhs: &'tcx Expr, span: Span) { + fn check_binop(self, cx: &LateContext<'a, 'tcx>, op: BinOpKind, lhs: &'tcx Expr, rhs: &'tcx Expr, span: Span) { let (lkind, llhs, lrhs, rkind, rlhs, rrhs) = match (lhs.node.clone(), rhs.node.clone()) { (ExprKind::Binary(lb, llhs, lrhs), ExprKind::Binary(rb, rlhs, rrhs)) => { (lb.node, llhs, lrhs, rb.node, rlhs, rrhs) @@ -91,7 +81,7 @@ impl<'a, 'tcx> Pass { } } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DoubleComparisons { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if let ExprKind::Binary(ref kind, ref lhs, ref rhs) = expr.node { self.check_binop(cx, kind.node, lhs, rhs, expr.span); diff --git a/clippy_lints/src/double_parens.rs b/clippy_lints/src/double_parens.rs index 5b5639371a18..12f67b84ca28 100644 --- a/clippy_lints/src/double_parens.rs +++ b/clippy_lints/src/double_parens.rs @@ -1,6 +1,6 @@ use crate::utils::{in_macro, span_lint}; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use syntax::ast::*; declare_clippy_lint! { @@ -22,18 +22,7 @@ declare_clippy_lint! { "Warn on unnecessary double parentheses" } -#[derive(Copy, Clone)] -pub struct DoubleParens; - -impl LintPass for DoubleParens { - fn get_lints(&self) -> LintArray { - lint_array!(DOUBLE_PARENS) - } - - fn name(&self) -> &'static str { - "DoubleParens" - } -} +declare_lint_pass!(DoubleParens => [DOUBLE_PARENS]); impl EarlyLintPass for DoubleParens { fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { diff --git a/clippy_lints/src/drop_bounds.rs b/clippy_lints/src/drop_bounds.rs index 702f7eced717..4c7c866fc635 100644 --- a/clippy_lints/src/drop_bounds.rs +++ b/clippy_lints/src/drop_bounds.rs @@ -1,8 +1,8 @@ -use crate::utils::{match_def_path, paths, span_lint}; +use crate::utils::{paths, span_lint}; use if_chain::if_chain; use rustc::hir::*; use rustc::lint::{LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { /// **What it does:** Checks for generics with `std::ops::Drop` as bounds. @@ -35,19 +35,9 @@ declare_clippy_lint! { const DROP_BOUNDS_SUMMARY: &str = "Bounds of the form `T: Drop` are useless. \ Use `std::mem::needs_drop` to detect if a type has drop glue."; -pub struct Pass; +declare_lint_pass!(DropBounds => [DROP_BOUNDS]); -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(DROP_BOUNDS) - } - - fn name(&self) -> &'static str { - "DropBounds" - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DropBounds { fn check_generic_param(&mut self, cx: &rustc::lint::LateContext<'a, 'tcx>, p: &'tcx GenericParam) { for bound in &p.bounds { lint_bound(cx, bound); @@ -66,7 +56,7 @@ fn lint_bound<'a, 'tcx>(cx: &rustc::lint::LateContext<'a, 'tcx>, bound: &'tcx Ge if_chain! { if let GenericBound::Trait(t, _) = bound; if let Some(def_id) = t.trait_ref.path.def.opt_def_id(); - if match_def_path(cx.tcx, def_id, &paths::DROP_TRAIT); + if cx.match_def_path(def_id, &paths::DROP_TRAIT); then { span_lint( cx, diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs index b880e28fc647..44853cd79903 100644 --- a/clippy_lints/src/drop_forget_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -1,9 +1,9 @@ -use crate::utils::{is_copy, match_def_path, paths, span_note_and_lint}; +use crate::utils::{is_copy, paths, span_note_and_lint}; use if_chain::if_chain; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::ty; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { /// **What it does:** Checks for calls to `std::mem::drop` with a reference @@ -106,19 +106,9 @@ const DROP_COPY_SUMMARY: &str = "calls to `std::mem::drop` with a value that imp const FORGET_COPY_SUMMARY: &str = "calls to `std::mem::forget` with a value that implements Copy. \ Forgetting a copy leaves the original intact."; -pub struct Pass; +declare_lint_pass!(DropForgetRef => [DROP_REF, FORGET_REF, DROP_COPY, FORGET_COPY]); -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(DROP_REF, FORGET_REF, DROP_COPY, FORGET_COPY) - } - - fn name(&self) -> &'static str { - "DropForgetRef" - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DropForgetRef { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if_chain! { if let ExprKind::Call(ref path, ref args) = expr.node; @@ -132,10 +122,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let arg_ty = cx.tables.expr_ty(arg); if let ty::Ref(..) = arg_ty.sty { - if match_def_path(cx.tcx, def_id, &paths::DROP) { + if cx.match_def_path(def_id, &paths::DROP) { lint = DROP_REF; msg = DROP_REF_SUMMARY.to_string(); - } else if match_def_path(cx.tcx, def_id, &paths::MEM_FORGET) { + } else if cx.match_def_path(def_id, &paths::MEM_FORGET) { lint = FORGET_REF; msg = FORGET_REF_SUMMARY.to_string(); } else { @@ -148,10 +138,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { arg.span, &format!("argument has type {}", arg_ty)); } else if is_copy(cx, arg_ty) { - if match_def_path(cx.tcx, def_id, &paths::DROP) { + if cx.match_def_path(def_id, &paths::DROP) { lint = DROP_COPY; msg = DROP_COPY_SUMMARY.to_string(); - } else if match_def_path(cx.tcx, def_id, &paths::MEM_FORGET) { + } else if cx.match_def_path(def_id, &paths::MEM_FORGET) { lint = FORGET_COPY; msg = FORGET_COPY_SUMMARY.to_string(); } else { diff --git a/clippy_lints/src/duration_subsec.rs b/clippy_lints/src/duration_subsec.rs index df0ea31470c6..60470ede5419 100644 --- a/clippy_lints/src/duration_subsec.rs +++ b/clippy_lints/src/duration_subsec.rs @@ -1,7 +1,7 @@ use if_chain::if_chain; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; use syntax::source_map::Spanned; @@ -29,18 +29,7 @@ declare_clippy_lint! { "checks for calculation of subsecond microseconds or milliseconds" } -#[derive(Copy, Clone)] -pub struct DurationSubsec; - -impl LintPass for DurationSubsec { - fn get_lints(&self) -> LintArray { - lint_array!(DURATION_SUBSEC) - } - - fn name(&self) -> &'static str { - "DurationSubsec" - } -} +declare_lint_pass!(DurationSubsec => [DURATION_SUBSEC]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DurationSubsec { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { diff --git a/clippy_lints/src/else_if_without_else.rs b/clippy_lints/src/else_if_without_else.rs index 01380fd96807..25a1cde6e5ee 100644 --- a/clippy_lints/src/else_if_without_else.rs +++ b/clippy_lints/src/else_if_without_else.rs @@ -1,7 +1,7 @@ //! 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::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use syntax::ast::*; use crate::utils::span_help_and_lint; @@ -39,18 +39,7 @@ declare_clippy_lint! { "if expression with an `else if`, but without a final `else` branch" } -#[derive(Copy, Clone)] -pub struct ElseIfWithoutElse; - -impl LintPass for ElseIfWithoutElse { - fn get_lints(&self) -> LintArray { - lint_array!(ELSE_IF_WITHOUT_ELSE) - } - - fn name(&self) -> &'static str { - "ElseIfWithoutElse" - } -} +declare_lint_pass!(ElseIfWithoutElse => [ELSE_IF_WITHOUT_ELSE]); impl EarlyLintPass for ElseIfWithoutElse { fn check_expr(&mut self, cx: &EarlyContext<'_>, mut item: &Expr) { diff --git a/clippy_lints/src/empty_enum.rs b/clippy_lints/src/empty_enum.rs index 9075cdc10c8b..e8d25384ee6a 100644 --- a/clippy_lints/src/empty_enum.rs +++ b/clippy_lints/src/empty_enum.rs @@ -3,7 +3,7 @@ use crate::utils::span_lint_and_then; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { /// **What it does:** Checks for `enum`s with no variants. @@ -23,18 +23,7 @@ declare_clippy_lint! { "enum with no variants" } -#[derive(Copy, Clone)] -pub struct EmptyEnum; - -impl LintPass for EmptyEnum { - fn get_lints(&self) -> LintArray { - lint_array!(EMPTY_ENUM) - } - - fn name(&self) -> &'static str { - "EmptyEnum" - } -} +declare_lint_pass!(EmptyEnum => [EMPTY_ENUM]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EmptyEnum { fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &Item) { diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index 0dc970fcafe2..c74232a906e1 100644 --- a/clippy_lints/src/entry.rs +++ b/clippy_lints/src/entry.rs @@ -4,7 +4,7 @@ use if_chain::if_chain; use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; use syntax::source_map::Span; @@ -37,20 +37,9 @@ declare_clippy_lint! { "use of `contains_key` followed by `insert` on a `HashMap` or `BTreeMap`" } -#[derive(Copy, Clone)] -pub struct HashMapLint; +declare_lint_pass!(HashMapPass => [MAP_ENTRY]); -impl LintPass for HashMapLint { - fn get_lints(&self) -> LintArray { - lint_array!(MAP_ENTRY) - } - - fn name(&self) -> &'static str { - "HashMap" - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for HashMapLint { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for HashMapPass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if let ExprKind::If(ref check, ref then_block, ref else_block) = expr.node { if let ExprKind::Unary(UnOp::UnNot, ref check) = check.node { diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs index 8e844f9c3988..90cb78ae0366 100644 --- a/clippy_lints/src/enum_clike.rs +++ b/clippy_lints/src/enum_clike.rs @@ -9,7 +9,7 @@ use rustc::mir::interpret::GlobalId; use rustc::ty; use rustc::ty::subst::InternalSubsts; use rustc::ty::util::IntTypeExt; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use syntax::ast::{IntTy, UintTy}; declare_clippy_lint! { @@ -34,17 +34,7 @@ declare_clippy_lint! { "C-like enums that are `repr(isize/usize)` and have values that don't fit into an `i32`" } -pub struct UnportableVariant; - -impl LintPass for UnportableVariant { - fn get_lints(&self) -> LintArray { - lint_array!(ENUM_CLIKE_UNPORTABLE_VARIANT) - } - - fn name(&self) -> &'static str { - "UnportableVariant" - } -} +declare_lint_pass!(UnportableVariant => [ENUM_CLIKE_UNPORTABLE_VARIANT]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnportableVariant { #[allow(clippy::cast_possible_truncation, clippy::cast_possible_wrap, clippy::cast_sign_loss)] diff --git a/clippy_lints/src/enum_glob_use.rs b/clippy_lints/src/enum_glob_use.rs index afdf27376d80..673f471b83c0 100644 --- a/clippy_lints/src/enum_glob_use.rs +++ b/clippy_lints/src/enum_glob_use.rs @@ -4,7 +4,7 @@ use crate::utils::span_lint; use rustc::hir::def::Def; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use syntax::source_map::Span; declare_clippy_lint! { @@ -25,17 +25,7 @@ declare_clippy_lint! { "use items that import all variants of an enum" } -pub struct EnumGlobUse; - -impl LintPass for EnumGlobUse { - fn get_lints(&self) -> LintArray { - lint_array!(ENUM_GLOB_USE) - } - - fn name(&self) -> &'static str { - "EnumGlobUse" - } -} +declare_lint_pass!(EnumGlobUse => [ENUM_GLOB_USE]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EnumGlobUse { fn check_mod(&mut self, cx: &LateContext<'a, 'tcx>, m: &'tcx Mod, _: Span, _: HirId) { @@ -48,7 +38,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EnumGlobUse { } impl EnumGlobUse { - fn lint_item(&self, cx: &LateContext<'_, '_>, item: &Item) { + fn lint_item(self, cx: &LateContext<'_, '_>, item: &Item) { if item.vis.node.is_pub() { return; // re-exports are fine } diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index 707fe93bd0c3..27229710641d 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -1,9 +1,9 @@ //! lint on enum variants that are prefixed or suffixed by the same characters -use crate::utils::{camel_case, in_macro}; +use crate::utils::{camel_case, in_macro, is_present_in_source}; use crate::utils::{span_help_and_lint, span_lint}; use rustc::lint::{EarlyContext, EarlyLintPass, Lint, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_tool_lint, impl_lint_pass}; use syntax::ast::*; use syntax::source_map::Span; use syntax::symbol::{InternedString, LocalInternedString}; @@ -115,20 +115,12 @@ impl EnumVariantNames { } } -impl LintPass for EnumVariantNames { - fn get_lints(&self) -> LintArray { - lint_array!( - ENUM_VARIANT_NAMES, - PUB_ENUM_VARIANT_NAMES, - MODULE_NAME_REPETITIONS, - MODULE_INCEPTION - ) - } - - fn name(&self) -> &'static str { - "EnumVariantNames" - } -} +impl_lint_pass!(EnumVariantNames => [ + ENUM_VARIANT_NAMES, + PUB_ENUM_VARIANT_NAMES, + MODULE_NAME_REPETITIONS, + MODULE_INCEPTION +]); fn var2str(var: &Variant) -> LocalInternedString { var.node.ident.as_str() @@ -252,7 +244,7 @@ impl EarlyLintPass for EnumVariantNames { let item_name = item.ident.as_str(); let item_name_chars = item_name.chars().count(); let item_camel = to_camel_case(&item_name); - if !in_macro(item.span) { + if !in_macro(item.span) && is_present_in_source(cx, item.span) { if let Some(&(ref mod_name, ref mod_camel)) = self.modules.last() { // constants don't have surrounding modules if !mod_camel.is_empty() { diff --git a/clippy_lints/src/eq_op.rs b/clippy_lints/src/eq_op.rs index 1f42a06fbcd3..ea09f82642f7 100644 --- a/clippy_lints/src/eq_op.rs +++ b/clippy_lints/src/eq_op.rs @@ -3,7 +3,7 @@ use crate::utils::{ }; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; declare_clippy_lint! { @@ -46,18 +46,7 @@ declare_clippy_lint! { "taking a reference to satisfy the type constraints on `==`" } -#[derive(Copy, Clone)] -pub struct EqOp; - -impl LintPass for EqOp { - fn get_lints(&self) -> LintArray { - lint_array!(EQ_OP, OP_REF) - } - - fn name(&self) -> &'static str { - "EqOp" - } -} +declare_lint_pass!(EqOp => [EQ_OP, OP_REF]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { #[allow(clippy::similar_names, clippy::too_many_lines)] diff --git a/clippy_lints/src/erasing_op.rs b/clippy_lints/src/erasing_op.rs index 07909ef587fe..7f3549be64bb 100644 --- a/clippy_lints/src/erasing_op.rs +++ b/clippy_lints/src/erasing_op.rs @@ -1,6 +1,6 @@ use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use syntax::source_map::Span; use crate::consts::{constant_simple, Constant}; @@ -27,18 +27,7 @@ declare_clippy_lint! { "using erasing operations, e.g., `x * 0` or `y & 0`" } -#[derive(Copy, Clone)] -pub struct ErasingOp; - -impl LintPass for ErasingOp { - fn get_lints(&self) -> LintArray { - lint_array!(ERASING_OP) - } - - fn name(&self) -> &'static str { - "ErasingOp" - } -} +declare_lint_pass!(ErasingOp => [ERASING_OP]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ErasingOp { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index 59ca2563cda6..8870b3f3b0ce 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -6,12 +6,13 @@ use rustc::middle::mem_categorization::{cmt_, Categorization}; use rustc::ty::layout::LayoutOf; use rustc::ty::{self, Ty}; use rustc::util::nodemap::HirIdSet; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_tool_lint, impl_lint_pass}; use syntax::source_map::Span; use crate::utils::span_lint; -pub struct Pass { +#[derive(Copy, Clone)] +pub struct BoxedLocal { pub too_large_for_stack: u64, } @@ -48,17 +49,9 @@ struct EscapeDelegate<'a, 'tcx: 'a> { too_large_for_stack: u64, } -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(BOXED_LOCAL) - } - - fn name(&self) -> &'static str { - "BoxedLocal" - } -} +impl_lint_pass!(BoxedLocal => [BOXED_LOCAL]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoxedLocal { fn check_fn( &mut self, cx: &LateContext<'a, 'tcx>, diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index d67381660e51..63abe47b4428 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -2,13 +2,11 @@ use if_chain::if_chain; use rustc::hir::*; use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass}; use rustc::ty::{self, Ty}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; 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; - declare_clippy_lint! { /// **What it does:** Checks for closures which just call another function where /// the function can be called directly. `unsafe` functions or calls where types @@ -33,17 +31,9 @@ declare_clippy_lint! { "redundant closures, i.e., `|a| foo(a)` (which can be written as just `foo`)" } -impl LintPass for EtaPass { - fn get_lints(&self) -> LintArray { - lint_array!(REDUNDANT_CLOSURE) - } - - fn name(&self) -> &'static str { - "EtaReduction" - } -} +declare_lint_pass!(EtaReduction => [REDUNDANT_CLOSURE]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EtaPass { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EtaReduction { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if in_external_macro(cx.sess(), expr.span) { return; diff --git a/clippy_lints/src/eval_order_dependence.rs b/clippy_lints/src/eval_order_dependence.rs index 2a4d404ccc7f..a62bb3cda9b6 100644 --- a/clippy_lints/src/eval_order_dependence.rs +++ b/clippy_lints/src/eval_order_dependence.rs @@ -4,7 +4,7 @@ use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::ty; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { /// **What it does:** Checks for a read and a write to the same variable where @@ -53,18 +53,7 @@ declare_clippy_lint! { "whether an expression contains a diverging sub expression" } -#[derive(Copy, Clone)] -pub struct EvalOrderDependence; - -impl LintPass for EvalOrderDependence { - fn get_lints(&self) -> LintArray { - lint_array!(EVAL_ORDER_DEPENDENCE, DIVERGING_SUB_EXPRESSION) - } - - fn name(&self) -> &'static str { - "EvalOrderDependence" - } -} +declare_lint_pass!(EvalOrderDependence => [EVAL_ORDER_DEPENDENCE, DIVERGING_SUB_EXPRESSION]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EvalOrderDependence { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { diff --git a/clippy_lints/src/excessive_precision.rs b/clippy_lints/src/excessive_precision.rs index ff28866e3a7b..5f631237885c 100644 --- a/clippy_lints/src/excessive_precision.rs +++ b/clippy_lints/src/excessive_precision.rs @@ -3,7 +3,7 @@ use if_chain::if_chain; use rustc::hir; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::ty; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; use std::f32; use std::f64; @@ -35,17 +35,7 @@ declare_clippy_lint! { "excessive precision for float literal" } -pub struct ExcessivePrecision; - -impl LintPass for ExcessivePrecision { - fn get_lints(&self) -> LintArray { - lint_array!(EXCESSIVE_PRECISION) - } - - fn name(&self) -> &'static str { - "ExcessivePrecision" - } -} +declare_lint_pass!(ExcessivePrecision => [EXCESSIVE_PRECISION]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExcessivePrecision { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) { @@ -72,7 +62,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExcessivePrecision { impl ExcessivePrecision { // None if nothing to lint, Some(suggestion) if lint necessary - fn check(&self, sym: Symbol, fty: FloatTy) -> Option { + fn check(self, sym: Symbol, fty: FloatTy) -> Option { let max = max_digits(fty); let sym_str = sym.as_str(); if dot_zero_exclusion(&sym_str) { diff --git a/clippy_lints/src/explicit_write.rs b/clippy_lints/src/explicit_write.rs index 64ba3efedc5e..a29b1380006c 100644 --- a/clippy_lints/src/explicit_write.rs +++ b/clippy_lints/src/explicit_write.rs @@ -1,8 +1,8 @@ -use crate::utils::{is_expn_of, match_def_path, resolve_node, span_lint, span_lint_and_sugg}; +use crate::utils::{is_expn_of, resolve_node, span_lint, span_lint_and_sugg}; use if_chain::if_chain; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; use syntax::ast::LitKind; @@ -24,20 +24,9 @@ declare_clippy_lint! { "using the `write!()` family of functions instead of the `print!()` family of functions, when using the latter would work" } -#[derive(Copy, Clone, Debug)] -pub struct Pass; +declare_lint_pass!(ExplicitWrite => [EXPLICIT_WRITE]); -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(EXPLICIT_WRITE) - } - - fn name(&self) -> &'static str { - "ExplicitWrite" - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExplicitWrite { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if_chain! { // match call to unwrap @@ -54,9 +43,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if let ExprKind::Path(ref qpath) = dest_fun.node; if let Some(dest_fun_id) = resolve_node(cx, qpath, dest_fun.hir_id).opt_def_id(); - if let Some(dest_name) = if match_def_path(cx.tcx, dest_fun_id, &["std", "io", "stdio", "stdout"]) { + if let Some(dest_name) = if cx.match_def_path(dest_fun_id, &["std", "io", "stdio", "stdout"]) { Some("stdout") - } else if match_def_path(cx.tcx, dest_fun_id, &["std", "io", "stdio", "stderr"]) { + } else if cx.match_def_path(dest_fun_id, &["std", "io", "stdio", "stderr"]) { Some("stderr") } else { None diff --git a/clippy_lints/src/fallible_impl_from.rs b/clippy_lints/src/fallible_impl_from.rs index bed5964fb32f..1cbe9d218bdf 100644 --- a/clippy_lints/src/fallible_impl_from.rs +++ b/clippy_lints/src/fallible_impl_from.rs @@ -1,10 +1,10 @@ use crate::utils::paths::{BEGIN_PANIC, BEGIN_PANIC_FMT, FROM_TRAIT, OPTION, RESULT}; -use crate::utils::{is_expn_of, match_def_path, method_chain_args, span_lint_and_then, walk_ptrs_ty}; +use crate::utils::{is_expn_of, method_chain_args, span_lint_and_then, walk_ptrs_ty}; use if_chain::if_chain; use rustc::hir; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::ty::{self, Ty}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use syntax_pos::Span; declare_clippy_lint! { @@ -28,17 +28,7 @@ declare_clippy_lint! { "Warn on impls of `From<..>` that contain `panic!()` or `unwrap()`" } -pub struct FallibleImplFrom; - -impl LintPass for FallibleImplFrom { - fn get_lints(&self) -> LintArray { - lint_array!(FALLIBLE_IMPL_FROM) - } - - fn name(&self) -> &'static str { - "FallibleImpleFrom" - } -} +declare_lint_pass!(FallibleImplFrom => [FALLIBLE_IMPL_FROM]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FallibleImplFrom { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::Item) { @@ -47,7 +37,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FallibleImplFrom { if_chain! { if let hir::ItemKind::Impl(.., ref impl_items) = item.node; if let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(impl_def_id); - if match_def_path(cx.tcx, impl_trait_ref.def_id, &FROM_TRAIT); + if cx.match_def_path(impl_trait_ref.def_id, &FROM_TRAIT); then { lint_impl_body(cx, item.span, impl_items); } @@ -60,7 +50,7 @@ fn lint_impl_body<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, impl_span: Span, impl_it use rustc::hir::*; struct FindPanicUnwrap<'a, 'tcx: 'a> { - tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, + lcx: &'a LateContext<'a, 'tcx>, tables: &'tcx ty::TypeckTables<'tcx>, result: Vec, } @@ -72,8 +62,8 @@ fn lint_impl_body<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, impl_span: Span, impl_it if let ExprKind::Call(ref func_expr, _) = expr.node; if let ExprKind::Path(QPath::Resolved(_, ref path)) = func_expr.node; if let Some(path_def_id) = path.def.opt_def_id(); - if match_def_path(self.tcx, path_def_id, &BEGIN_PANIC) || - match_def_path(self.tcx, path_def_id, &BEGIN_PANIC_FMT); + if self.lcx.match_def_path(path_def_id, &BEGIN_PANIC) || + self.lcx.match_def_path(path_def_id, &BEGIN_PANIC_FMT); if is_expn_of(expr.span, "unreachable").is_none(); then { self.result.push(expr.span); @@ -83,7 +73,7 @@ fn lint_impl_body<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, impl_span: Span, impl_it // check for `unwrap` if let Some(arglists) = method_chain_args(expr, &["unwrap"]) { let reciever_ty = walk_ptrs_ty(self.tables.expr_ty(&arglists[0][0])); - if match_type(self.tcx, reciever_ty, &OPTION) || match_type(self.tcx, reciever_ty, &RESULT) { + if match_type(self.lcx, reciever_ty, &OPTION) || match_type(self.lcx, reciever_ty, &RESULT) { self.result.push(expr.span); } } @@ -107,7 +97,7 @@ fn lint_impl_body<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, impl_span: Span, impl_it let body = cx.tcx.hir().body(body_id); let impl_item_def_id = cx.tcx.hir().local_def_id_from_hir_id(impl_item.id.hir_id); let mut fpu = FindPanicUnwrap { - tcx: cx.tcx, + lcx: cx, tables: cx.tcx.typeck_tables_of(impl_item_def_id), result: Vec::new(), }; @@ -132,9 +122,9 @@ fn lint_impl_body<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, impl_span: Span, impl_it } } -fn match_type<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'_>, path: &[&str]) -> bool { +fn match_type(cx: &LateContext<'_, '_>, ty: Ty<'_>, path: &[&str]) -> bool { match ty.sty { - ty::Adt(adt, _) => match_def_path(tcx, adt.did, path), + ty::Adt(adt, _) => cx.match_def_path(adt.did, path), _ => false, } } diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index 542823c2b8e6..95389fa3c81e 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -1,13 +1,12 @@ use crate::utils::paths; use crate::utils::{ - in_macro, is_expn_of, last_path_segment, match_def_path, match_type, resolve_node, snippet, span_lint_and_then, - walk_ptrs_ty, + in_macro, is_expn_of, last_path_segment, match_type, resolve_node, snippet, span_lint_and_then, walk_ptrs_ty, }; use if_chain::if_chain; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintContext, LintPass}; use rustc::ty; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; use syntax::ast::LitKind; use syntax::source_map::Span; @@ -34,20 +33,9 @@ declare_clippy_lint! { "useless use of `format!`" } -#[derive(Copy, Clone, Debug)] -pub struct Pass; +declare_lint_pass!(UselessFormat => [USELESS_FORMAT]); -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array![USELESS_FORMAT] - } - - fn name(&self) -> &'static str { - "UselessFormat" - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessFormat { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if let Some(span) = is_expn_of(expr.span, "format") { if in_macro(span) { @@ -59,9 +47,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if_chain! { if let ExprKind::Path(ref qpath) = fun.node; if let Some(fun_def_id) = resolve_node(cx, qpath, fun.hir_id).opt_def_id(); - let new_v1 = match_def_path(cx.tcx, fun_def_id, &paths::FMT_ARGUMENTS_NEWV1); - let new_v1_fmt = match_def_path( - cx.tcx, + let new_v1 = cx.match_def_path(fun_def_id, &paths::FMT_ARGUMENTS_NEWV1); + let new_v1_fmt = cx.match_def_path( fun_def_id, &paths::FMT_ARGUMENTS_NEWV1FORMATTED ); @@ -162,7 +149,7 @@ fn get_single_string_arg<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr) -> Option if args.len() == 2; if let ExprKind::Path(ref qpath) = args[1].node; if let Some(fun_def_id) = resolve_node(cx, qpath, args[1].hir_id).opt_def_id(); - if match_def_path(cx.tcx, fun_def_id, &paths::DISPLAY_FMT_METHOD); + if cx.match_def_path(fun_def_id, &paths::DISPLAY_FMT_METHOD); then { let ty = walk_ptrs_ty(cx.tables.pat_ty(&pat[0])); if ty.sty == ty::Str || match_type(cx, ty, &paths::STRING) { diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs index 542392c8b29b..e29a8c3702b1 100644 --- a/clippy_lints/src/formatting.rs +++ b/clippy_lints/src/formatting.rs @@ -1,7 +1,7 @@ use crate::utils::{differing_macro_contexts, in_macro, snippet_opt, span_note_and_lint}; use if_chain::if_chain; use rustc::lint::{in_external_macro, EarlyContext, EarlyLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use syntax::ast; use syntax::ptr::P; @@ -79,22 +79,11 @@ declare_clippy_lint! { "possible missing comma in array" } -#[derive(Copy, Clone)] -pub struct Formatting; - -impl LintPass for Formatting { - fn get_lints(&self) -> LintArray { - lint_array!( - SUSPICIOUS_ASSIGNMENT_FORMATTING, - SUSPICIOUS_ELSE_FORMATTING, - POSSIBLE_MISSING_COMMA - ) - } - - fn name(&self) -> &'static str { - "Formatting" - } -} +declare_lint_pass!(Formatting => [ + SUSPICIOUS_ASSIGNMENT_FORMATTING, + SUSPICIOUS_ELSE_FORMATTING, + POSSIBLE_MISSING_COMMA +]); impl EarlyLintPass for Formatting { fn check_block(&mut self, cx: &EarlyContext<'_>, block: &ast::Block) { diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index d657bb6a0b4e..b3e0eb8a6704 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -5,7 +5,7 @@ use rustc::hir::def::Def; use rustc::hir::intravisit; use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass}; use rustc::ty; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_tool_lint, impl_lint_pass}; use rustc_data_structures::fx::FxHashSet; use rustc_target::spec::abi::Abi; use syntax::source_map::Span; @@ -93,15 +93,7 @@ impl Functions { } } -impl LintPass for Functions { - fn get_lints(&self) -> LintArray { - lint_array!(TOO_MANY_ARGUMENTS, TOO_MANY_LINES, NOT_UNSAFE_PTR_ARG_DEREF) - } - - fn name(&self) -> &'static str { - "Functions" - } -} +impl_lint_pass!(Functions => [TOO_MANY_ARGUMENTS, TOO_MANY_LINES, NOT_UNSAFE_PTR_ARG_DEREF]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Functions { fn check_fn( diff --git a/clippy_lints/src/identity_conversion.rs b/clippy_lints/src/identity_conversion.rs index 7391f0a5208e..0941ed513fc4 100644 --- a/clippy_lints/src/identity_conversion.rs +++ b/clippy_lints/src/identity_conversion.rs @@ -1,10 +1,8 @@ -use crate::utils::{ - in_macro, match_def_path, match_trait_method, same_tys, snippet, snippet_with_macro_callsite, span_lint_and_then, -}; +use crate::utils::{in_macro, match_trait_method, same_tys, snippet, snippet_with_macro_callsite, span_lint_and_then}; use crate::utils::{paths, resolve_node}; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_tool_lint, impl_lint_pass}; use rustc_errors::Applicability; declare_clippy_lint! { @@ -29,15 +27,7 @@ pub struct IdentityConversion { try_desugar_arm: Vec, } -impl LintPass for IdentityConversion { - fn get_lints(&self) -> LintArray { - lint_array!(IDENTITY_CONVERSION) - } - - fn name(&self) -> &'static str { - "IdentityConversion" - } -} +impl_lint_pass!(IdentityConversion => [IDENTITY_CONVERSION]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityConversion { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { @@ -99,7 +89,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityConversion { ExprKind::Call(ref path, ref args) => { if let ExprKind::Path(ref qpath) = path.node { if let Some(def_id) = resolve_node(cx, qpath, path.hir_id).opt_def_id() { - if match_def_path(cx.tcx, def_id, &paths::FROM_FROM[..]) { + if cx.match_def_path(def_id, &paths::FROM_FROM[..]) { let a = cx.tables.expr_ty(e); let b = cx.tables.expr_ty(&args[0]); if same_tys(cx, a, b) { diff --git a/clippy_lints/src/identity_op.rs b/clippy_lints/src/identity_op.rs index 6d15e37454c4..cc023a5a4598 100644 --- a/clippy_lints/src/identity_op.rs +++ b/clippy_lints/src/identity_op.rs @@ -1,7 +1,7 @@ use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::ty; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use syntax::source_map::Span; use crate::consts::{constant_simple, Constant}; @@ -24,18 +24,7 @@ declare_clippy_lint! { "using identity operations, e.g., `x + 0` or `y / 1`" } -#[derive(Copy, Clone)] -pub struct IdentityOp; - -impl LintPass for IdentityOp { - fn get_lints(&self) -> LintArray { - lint_array!(IDENTITY_OP) - } - - fn name(&self) -> &'static str { - "IdentityOp" - } -} +declare_lint_pass!(IdentityOp => [IDENTITY_OP]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityOp { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { diff --git a/clippy_lints/src/if_not_else.rs b/clippy_lints/src/if_not_else.rs index 5ce29597cab7..385ba9f16c89 100644 --- a/clippy_lints/src/if_not_else.rs +++ b/clippy_lints/src/if_not_else.rs @@ -2,7 +2,7 @@ //! on the condition use rustc::lint::{in_external_macro, EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use syntax::ast::*; use crate::utils::span_help_and_lint; @@ -38,17 +38,7 @@ declare_clippy_lint! { "`if` branches that could be swapped so no negation operation is necessary on the condition" } -pub struct IfNotElse; - -impl LintPass for IfNotElse { - fn get_lints(&self) -> LintArray { - lint_array!(IF_NOT_ELSE) - } - - fn name(&self) -> &'static str { - "IfNotElse" - } -} +declare_lint_pass!(IfNotElse => [IF_NOT_ELSE]); impl EarlyLintPass for IfNotElse { fn check_expr(&mut self, cx: &EarlyContext<'_>, item: &Expr) { diff --git a/clippy_lints/src/implicit_return.rs b/clippy_lints/src/implicit_return.rs index a82a57fe6ff3..559b0942d2b5 100644 --- a/clippy_lints/src/implicit_return.rs +++ b/clippy_lints/src/implicit_return.rs @@ -1,7 +1,7 @@ use crate::utils::{in_macro, is_expn_of, snippet_opt, span_lint_and_then}; use rustc::hir::{intravisit::FnKind, Body, ExprKind, FnDecl, HirId, MatchSource}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; use syntax::source_map::Span; @@ -33,9 +33,9 @@ declare_clippy_lint! { "use a return statement like `return expr` instead of an expression" } -pub struct Pass; +declare_lint_pass!(ImplicitReturn => [IMPLICIT_RETURN]); -impl Pass { +impl ImplicitReturn { fn lint(cx: &LateContext<'_, '_>, outer_span: syntax_pos::Span, inner_span: syntax_pos::Span, msg: &str) { span_lint_and_then(cx, IMPLICIT_RETURN, outer_span, "missing return statement", |db| { if let Some(snippet) = snippet_opt(cx, inner_span) { @@ -110,17 +110,7 @@ impl Pass { } } -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(IMPLICIT_RETURN) - } - - fn name(&self) -> &'static str { - "ImplicitReturn" - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplicitReturn { fn check_fn( &mut self, cx: &LateContext<'a, 'tcx>, diff --git a/clippy_lints/src/indexing_slicing.rs b/clippy_lints/src/indexing_slicing.rs index 07fcec858637..d0a9bb729a45 100644 --- a/clippy_lints/src/indexing_slicing.rs +++ b/clippy_lints/src/indexing_slicing.rs @@ -7,7 +7,7 @@ use crate::utils::higher::Range; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::ty; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use syntax::ast::RangeLimits; declare_clippy_lint! { @@ -85,18 +85,7 @@ declare_clippy_lint! { "indexing/slicing usage" } -#[derive(Copy, Clone)] -pub struct IndexingSlicing; - -impl LintPass for IndexingSlicing { - fn get_lints(&self) -> LintArray { - lint_array!(INDEXING_SLICING, OUT_OF_BOUNDS_INDEXING) - } - - fn name(&self) -> &'static str { - "IndexSlicing" - } -} +declare_lint_pass!(IndexingSlicing => [INDEXING_SLICING, OUT_OF_BOUNDS_INDEXING]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IndexingSlicing { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { diff --git a/clippy_lints/src/infallible_destructuring_match.rs b/clippy_lints/src/infallible_destructuring_match.rs index 762d3b17c926..a977a827321d 100644 --- a/clippy_lints/src/infallible_destructuring_match.rs +++ b/clippy_lints/src/infallible_destructuring_match.rs @@ -2,7 +2,7 @@ use super::utils::{get_arg_name, match_var, remove_blocks, snippet_with_applicab use if_chain::if_chain; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; declare_clippy_lint! { @@ -40,20 +40,9 @@ declare_clippy_lint! { "a match statement with a single infallible arm instead of a `let`" } -#[derive(Copy, Clone, Default)] -pub struct Pass; +declare_lint_pass!(InfallibleDestructingMatch => [INFALLIBLE_DESTRUCTURING_MATCH]); -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(INFALLIBLE_DESTRUCTURING_MATCH) - } - - fn name(&self) -> &'static str { - "InfallibleDestructingMatch" - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InfallibleDestructingMatch { fn check_local(&mut self, cx: &LateContext<'a, 'tcx>, local: &'tcx Local) { if_chain! { if let Some(ref expr) = local.init; diff --git a/clippy_lints/src/infinite_iter.rs b/clippy_lints/src/infinite_iter.rs index 689cd8fd3b05..29e0396c09e3 100644 --- a/clippy_lints/src/infinite_iter.rs +++ b/clippy_lints/src/infinite_iter.rs @@ -1,6 +1,6 @@ use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use crate::utils::{get_trait_def_id, higher, implements_trait, match_qpath, match_type, paths, span_lint}; @@ -41,20 +41,9 @@ declare_clippy_lint! { "possible infinite iteration" } -#[derive(Copy, Clone)] -pub struct Pass; - -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(INFINITE_ITER, MAYBE_INFINITE_ITER) - } - - fn name(&self) -> &'static str { - "InfiniteIter" - } -} +declare_lint_pass!(InfiniteIter => [INFINITE_ITER, MAYBE_INFINITE_ITER]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InfiniteIter { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { let (lint, msg) = match complete_infinite_iter(cx, expr) { Infinite => (INFINITE_ITER, "infinite iteration detected"), diff --git a/clippy_lints/src/inherent_impl.rs b/clippy_lints/src/inherent_impl.rs index 51d6c310cf62..bde784f81de8 100644 --- a/clippy_lints/src/inherent_impl.rs +++ b/clippy_lints/src/inherent_impl.rs @@ -3,9 +3,8 @@ use crate::utils::span_lint_and_then; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_tool_lint, impl_lint_pass}; use rustc_data_structures::fx::FxHashMap; -use std::default::Default; use syntax_pos::Span; declare_clippy_lint! { @@ -40,29 +39,15 @@ declare_clippy_lint! { "Multiple inherent impl that could be grouped" } -pub struct Pass { +#[allow(clippy::module_name_repetitions)] +#[derive(Default)] +pub struct MultipleInherentImpl { impls: FxHashMap, } -impl Default for Pass { - fn default() -> Self { - Self { - impls: FxHashMap::default(), - } - } -} - -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(MULTIPLE_INHERENT_IMPL) - } - - fn name(&self) -> &'static str { - "MultipleInherientImpl" - } -} +impl_lint_pass!(MultipleInherentImpl => [MULTIPLE_INHERENT_IMPL]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MultipleInherentImpl { fn check_item(&mut self, _: &LateContext<'a, 'tcx>, item: &'tcx Item) { if let ItemKind::Impl(_, _, _, ref generics, None, _, _) = item.node { // Remember for each inherent implementation encoutered its span and generics diff --git a/clippy_lints/src/inline_fn_without_body.rs b/clippy_lints/src/inline_fn_without_body.rs index 3e13d0073fe8..5242b22c7908 100644 --- a/clippy_lints/src/inline_fn_without_body.rs +++ b/clippy_lints/src/inline_fn_without_body.rs @@ -4,7 +4,7 @@ use crate::utils::span_lint_and_then; use crate::utils::sugg::DiagnosticBuilderExt; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; use syntax::ast::{Attribute, Name}; @@ -28,20 +28,9 @@ declare_clippy_lint! { "use of `#[inline]` on trait methods without bodies" } -#[derive(Copy, Clone)] -pub struct Pass; +declare_lint_pass!(InlineFnWithoutBody => [INLINE_FN_WITHOUT_BODY]); -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(INLINE_FN_WITHOUT_BODY) - } - - fn name(&self) -> &'static str { - "InlineFnWithoutBody" - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InlineFnWithoutBody { fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem) { if let TraitItemKind::Method(_, TraitMethod::Required(_)) = item.node { check_attrs(cx, item.ident.name, &item.attrs); diff --git a/clippy_lints/src/int_plus_one.rs b/clippy_lints/src/int_plus_one.rs index bab7374916da..b59179618a6d 100644 --- a/clippy_lints/src/int_plus_one.rs +++ b/clippy_lints/src/int_plus_one.rs @@ -1,7 +1,7 @@ //! lint on blocks unnecessarily using >= with a + 1 or - 1 use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; use syntax::ast::*; @@ -30,17 +30,7 @@ declare_clippy_lint! { "instead of using x >= y + 1, use x > y" } -pub struct IntPlusOne; - -impl LintPass for IntPlusOne { - fn get_lints(&self) -> LintArray { - lint_array!(INT_PLUS_ONE) - } - - fn name(&self) -> &'static str { - "IntPlusOne" - } -} +declare_lint_pass!(IntPlusOne => [INT_PLUS_ONE]); // cases: // BinOpKind::Ge @@ -59,14 +49,14 @@ enum Side { impl IntPlusOne { #[allow(clippy::cast_sign_loss)] - fn check_lit(&self, lit: &Lit, target_value: i128) -> bool { + fn check_lit(self, lit: &Lit, target_value: i128) -> bool { if let LitKind::Int(value, ..) = lit.node { return value == (target_value as u128); } false } - fn check_binop(&self, cx: &EarlyContext<'_>, binop: BinOpKind, lhs: &Expr, rhs: &Expr) -> Option { + fn check_binop(self, cx: &EarlyContext<'_>, binop: BinOpKind, lhs: &Expr, rhs: &Expr) -> Option { match (binop, &lhs.node, &rhs.node) { // case where `x - 1 >= ...` or `-1 + x >= ...` (BinOpKind::Ge, &ExprKind::Binary(ref lhskind, ref lhslhs, ref lhsrhs), _) => { @@ -131,7 +121,7 @@ impl IntPlusOne { } fn generate_recommendation( - &self, + self, cx: &EarlyContext<'_>, binop: BinOpKind, node: &Expr, @@ -155,7 +145,7 @@ impl IntPlusOne { None } - fn emit_warning(&self, cx: &EarlyContext<'_>, block: &Expr, recommendation: String) { + fn emit_warning(self, cx: &EarlyContext<'_>, block: &Expr, recommendation: String) { span_lint_and_then( cx, INT_PLUS_ONE, diff --git a/clippy_lints/src/invalid_ref.rs b/clippy_lints/src/invalid_ref.rs index 721db396fff6..40a11cde4459 100644 --- a/clippy_lints/src/invalid_ref.rs +++ b/clippy_lints/src/invalid_ref.rs @@ -1,9 +1,9 @@ -use crate::utils::{match_def_path, paths, span_help_and_lint}; +use crate::utils::{paths, span_help_and_lint}; use if_chain::if_chain; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::ty; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { /// **What it does:** Checks for creation of references to zeroed or uninitialized memory. @@ -26,17 +26,7 @@ const UNINIT_REF_SUMMARY: &str = "reference to uninitialized memory"; const HELP: &str = "Creation of a null reference is undefined behavior; \ see https://doc.rust-lang.org/reference/behavior-considered-undefined.html"; -pub struct InvalidRef; - -impl LintPass for InvalidRef { - fn get_lints(&self) -> LintArray { - lint_array!(INVALID_REF) - } - - fn name(&self) -> &'static str { - "InvalidRef" - } -} +declare_lint_pass!(InvalidRef => [INVALID_REF]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidRef { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { @@ -47,12 +37,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidRef { if let ty::Ref(..) = cx.tables.expr_ty(expr).sty; if let Some(def_id) = cx.tables.qpath_def(qpath, path.hir_id).opt_def_id(); then { - let msg = if match_def_path(cx.tcx, def_id, &paths::MEM_ZEROED) | - match_def_path(cx.tcx, def_id, &paths::INIT) + let msg = if cx.match_def_path(def_id, &paths::MEM_ZEROED) | + cx.match_def_path(def_id, &paths::INIT) { ZERO_REF_SUMMARY - } else if match_def_path(cx.tcx, def_id, &paths::MEM_UNINIT) | - match_def_path(cx.tcx, def_id, &paths::UNINIT) + } else if cx.match_def_path(def_id, &paths::MEM_UNINIT) | + cx.match_def_path(def_id, &paths::UNINIT) { UNINIT_REF_SUMMARY } else { diff --git a/clippy_lints/src/items_after_statements.rs b/clippy_lints/src/items_after_statements.rs index f93f515d0239..779bac30e0fa 100644 --- a/clippy_lints/src/items_after_statements.rs +++ b/clippy_lints/src/items_after_statements.rs @@ -3,7 +3,7 @@ use crate::utils::{in_macro, span_lint}; use matches::matches; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use syntax::ast::*; declare_clippy_lint! { @@ -34,17 +34,7 @@ declare_clippy_lint! { "blocks where an item comes after a statement" } -pub struct ItemsAfterStatements; - -impl LintPass for ItemsAfterStatements { - fn get_lints(&self) -> LintArray { - lint_array!(ITEMS_AFTER_STATEMENTS) - } - - fn name(&self) -> &'static str { - "ItemsAfterStatements" - } -} +declare_lint_pass!(ItemsAfterStatements => [ITEMS_AFTER_STATEMENTS]); impl EarlyLintPass for ItemsAfterStatements { fn check_block(&mut self, cx: &EarlyContext<'_>, item: &Block) { diff --git a/clippy_lints/src/large_enum_variant.rs b/clippy_lints/src/large_enum_variant.rs index 2e38fcf03672..e447be82b03d 100644 --- a/clippy_lints/src/large_enum_variant.rs +++ b/clippy_lints/src/large_enum_variant.rs @@ -4,7 +4,7 @@ use crate::utils::{snippet_opt, span_lint_and_then}; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::ty::layout::LayoutOf; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_tool_lint, impl_lint_pass}; use rustc_errors::Applicability; declare_clippy_lint! { @@ -42,15 +42,7 @@ impl LargeEnumVariant { } } -impl LintPass for LargeEnumVariant { - fn get_lints(&self) -> LintArray { - lint_array!(LARGE_ENUM_VARIANT) - } - - fn name(&self) -> &'static str { - "LargeEnumVariant" - } -} +impl_lint_pass!(LargeEnumVariant => [LARGE_ENUM_VARIANT]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeEnumVariant { fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &Item) { diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 177c85adde58..191d27a1b8cf 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -3,7 +3,7 @@ use rustc::hir::def_id::DefId; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::ty; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use syntax::ast::{Lit, LitKind, Name}; @@ -69,18 +69,7 @@ declare_clippy_lint! { "traits or impls with a public `len` method but no corresponding `is_empty` method" } -#[derive(Copy, Clone)] -pub struct LenZero; - -impl LintPass for LenZero { - fn get_lints(&self) -> LintArray { - lint_array!(LEN_ZERO, LEN_WITHOUT_IS_EMPTY) - } - - fn name(&self) -> &'static str { - "LenZero" - } -} +declare_lint_pass!(LenZero => [LEN_ZERO, LEN_WITHOUT_IS_EMPTY]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LenZero { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index 1f454c4983a9..f5da2d7803e3 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -4,7 +4,7 @@ use rustc::hir; use rustc::hir::def::Def; use rustc::hir::BindingAnnotation; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; declare_clippy_lint! { @@ -52,18 +52,7 @@ declare_clippy_lint! { "unidiomatic `let mut` declaration followed by initialization in `if`" } -#[derive(Copy, Clone)] -pub struct LetIfSeq; - -impl LintPass for LetIfSeq { - fn get_lints(&self) -> LintArray { - lint_array!(USELESS_LET_IF_SEQ) - } - - fn name(&self) -> &'static str { - "LetIfSeq" - } -} +declare_lint_pass!(LetIfSeq => [USELESS_LET_IF_SEQ]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetIfSeq { fn check_block(&mut self, cx: &LateContext<'a, 'tcx>, block: &'tcx hir::Block) { diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index d547e0a99b79..20560b9a3b4f 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -8,6 +8,7 @@ #![allow(clippy::missing_docs_in_private_items)] #![recursion_limit = "256"] #![warn(rust_2018_idioms, trivial_casts, trivial_numeric_casts)] +#![deny(internal)] #![feature(crate_visibility_modifier)] // FIXME: switch to something more ergonomic here, once available. @@ -235,6 +236,7 @@ pub mod open_options; pub mod overflow_check_conditional; pub mod panic_unimplemented; pub mod partialeq_ne_impl; +pub mod path_buf_push_overwrite; pub mod precedence; pub mod ptr; pub mod ptr_offset_with_cast; @@ -289,7 +291,7 @@ pub fn register_pre_expansion_lints( store: &mut rustc::lint::LintStore, conf: &Conf, ) { - store.register_pre_expansion_pass(Some(session), true, false, box write::Pass); + store.register_pre_expansion_pass(Some(session), true, false, box write::Write); store.register_pre_expansion_pass( Some(session), true, @@ -304,8 +306,14 @@ pub fn register_pre_expansion_lints( single_char_binding_names_threshold: conf.single_char_binding_names_threshold, }, ); - store.register_pre_expansion_pass(Some(session), true, false, box attrs::CfgAttrPass); - store.register_pre_expansion_pass(Some(session), true, false, box dbg_macro::Pass); + store.register_pre_expansion_pass(Some(session), true, false, box attrs::DeprecatedCfgAttribute); + store.register_pre_expansion_pass(Some(session), true, false, box dbg_macro::DbgMacro); + store.register_pre_expansion_pass( + Some(session), + true, + false, + box cognitive_complexity::CognitiveComplexity::new(conf.cognitive_complexity_threshold), + ) } #[doc(hidden)] @@ -370,6 +378,7 @@ pub fn read_conf(reg: &rustc_plugin::Registry<'_>) -> Conf { /// /// Used in `./src/driver.rs`. #[allow(clippy::too_many_lines)] +#[allow(clippy::cognitive_complexity)] #[rustfmt::skip] pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { let mut store = reg.sess.lint_store.borrow_mut(); @@ -420,14 +429,13 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { ); // end deprecated lints, do not remove this comment, it’s used in `update_lints` - reg.register_late_lint_pass(box serde_api::Serde); - reg.register_early_lint_pass(box utils::internal_lints::Clippy); + reg.register_late_lint_pass(box serde_api::SerdeAPI); + reg.register_early_lint_pass(box utils::internal_lints::ClippyLintsInternal); reg.register_late_lint_pass(box utils::internal_lints::CompilerLintFunctions::new()); - reg.register_early_lint_pass(box utils::internal_lints::DefaultHashTypes::default()); reg.register_late_lint_pass(box utils::internal_lints::LintWithoutLintPass::default()); - reg.register_late_lint_pass(box utils::inspector::Pass); - reg.register_late_lint_pass(box utils::author::Pass); - reg.register_late_lint_pass(box types::TypePass); + reg.register_late_lint_pass(box utils::inspector::DeepCodeInspector); + reg.register_late_lint_pass(box utils::author::Author); + reg.register_late_lint_pass(box types::Types); reg.register_late_lint_pass(box booleans::NonminimalBool); reg.register_late_lint_pass(box eq_op::EqOp); reg.register_early_lint_pass(box enum_variants::EnumVariantNames::new(conf.enum_variant_name_threshold)); @@ -435,68 +443,65 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_late_lint_pass(box enum_clike::UnportableVariant); reg.register_late_lint_pass(box excessive_precision::ExcessivePrecision); reg.register_late_lint_pass(box bit_mask::BitMask::new(conf.verbose_bit_mask_threshold)); - reg.register_late_lint_pass(box ptr::PointerPass); + reg.register_late_lint_pass(box ptr::Ptr); reg.register_late_lint_pass(box needless_bool::NeedlessBool); reg.register_late_lint_pass(box needless_bool::BoolComparison); - reg.register_late_lint_pass(box approx_const::Pass); - reg.register_late_lint_pass(box misc::Pass); + reg.register_late_lint_pass(box approx_const::ApproxConstant); + reg.register_late_lint_pass(box misc::MiscLints); reg.register_early_lint_pass(box precedence::Precedence); reg.register_early_lint_pass(box needless_continue::NeedlessContinue); - reg.register_late_lint_pass(box eta_reduction::EtaPass); + reg.register_late_lint_pass(box eta_reduction::EtaReduction); reg.register_late_lint_pass(box identity_op::IdentityOp); reg.register_late_lint_pass(box erasing_op::ErasingOp); reg.register_early_lint_pass(box items_after_statements::ItemsAfterStatements); reg.register_late_lint_pass(box mut_mut::MutMut); reg.register_late_lint_pass(box mut_reference::UnnecessaryMutPassed); reg.register_late_lint_pass(box len_zero::LenZero); - reg.register_late_lint_pass(box attrs::AttrPass); + reg.register_late_lint_pass(box attrs::Attributes); reg.register_early_lint_pass(box collapsible_if::CollapsibleIf); reg.register_late_lint_pass(box block_in_if_condition::BlockInIfCondition); reg.register_late_lint_pass(box unicode::Unicode); reg.register_late_lint_pass(box strings::StringAdd); - reg.register_early_lint_pass(box returns::ReturnPass); - reg.register_late_lint_pass(box implicit_return::Pass); - reg.register_late_lint_pass(box methods::Pass); - reg.register_late_lint_pass(box map_clone::Pass); - reg.register_late_lint_pass(box shadow::Pass); - reg.register_late_lint_pass(box types::LetPass); + reg.register_early_lint_pass(box returns::Return); + reg.register_late_lint_pass(box implicit_return::ImplicitReturn); + reg.register_late_lint_pass(box methods::Methods); + reg.register_late_lint_pass(box map_clone::MapClone); + reg.register_late_lint_pass(box shadow::Shadow); + reg.register_late_lint_pass(box types::LetUnitValue); reg.register_late_lint_pass(box types::UnitCmp); - reg.register_late_lint_pass(box loops::Pass); - reg.register_late_lint_pass(box lifetimes::LifetimePass); - reg.register_late_lint_pass(box entry::HashMapLint); - reg.register_late_lint_pass(box ranges::Pass); - reg.register_late_lint_pass(box types::CastPass); - reg.register_late_lint_pass(box types::TypeComplexityPass::new(conf.type_complexity_threshold)); - reg.register_late_lint_pass(box matches::MatchPass); + reg.register_late_lint_pass(box loops::Loops); + reg.register_late_lint_pass(box lifetimes::Lifetimes); + reg.register_late_lint_pass(box entry::HashMapPass); + reg.register_late_lint_pass(box ranges::Ranges); + reg.register_late_lint_pass(box types::Casts); + reg.register_late_lint_pass(box types::TypeComplexity::new(conf.type_complexity_threshold)); + reg.register_late_lint_pass(box matches::Matches); reg.register_late_lint_pass(box minmax::MinMaxPass); - reg.register_late_lint_pass(box open_options::NonSensical); - reg.register_late_lint_pass(box zero_div_zero::Pass); - reg.register_late_lint_pass(box mutex_atomic::MutexAtomic); - reg.register_late_lint_pass(box needless_update::Pass); + reg.register_late_lint_pass(box open_options::OpenOptions); + reg.register_late_lint_pass(box zero_div_zero::ZeroDiv); + reg.register_late_lint_pass(box mutex_atomic::Mutex); + reg.register_late_lint_pass(box needless_update::NeedlessUpdate); reg.register_late_lint_pass(box needless_borrow::NeedlessBorrow::default()); reg.register_late_lint_pass(box needless_borrowed_ref::NeedlessBorrowedRef); - reg.register_late_lint_pass(box no_effect::Pass); - reg.register_late_lint_pass(box temporary_assignment::Pass); + reg.register_late_lint_pass(box no_effect::NoEffect); + reg.register_late_lint_pass(box temporary_assignment::TemporaryAssignment); reg.register_late_lint_pass(box transmute::Transmute); - reg.register_late_lint_pass( - box cognitive_complexity::CognitiveComplexity::new(conf.cognitive_complexity_threshold) - ); - reg.register_late_lint_pass(box escape::Pass{too_large_for_stack: conf.too_large_for_stack}); - reg.register_early_lint_pass(box misc_early::MiscEarly); - reg.register_late_lint_pass(box panic_unimplemented::Pass); + reg.register_late_lint_pass(box escape::BoxedLocal{too_large_for_stack: conf.too_large_for_stack}); + reg.register_early_lint_pass(box misc_early::MiscEarlyLints); + reg.register_late_lint_pass(box panic_unimplemented::PanicUnimplemented); reg.register_late_lint_pass(box strings::StringLitAsBytes); reg.register_late_lint_pass(box derive::Derive); reg.register_late_lint_pass(box types::CharLitAsU8); - reg.register_late_lint_pass(box vec::Pass); - reg.register_late_lint_pass(box drop_bounds::Pass); - reg.register_late_lint_pass(box drop_forget_ref::Pass); + reg.register_late_lint_pass(box vec::UselessVec); + reg.register_late_lint_pass(box drop_bounds::DropBounds); + reg.register_late_lint_pass(box drop_forget_ref::DropForgetRef); reg.register_late_lint_pass(box empty_enum::EmptyEnum); reg.register_late_lint_pass(box types::AbsurdExtremeComparisons); reg.register_late_lint_pass(box types::InvalidUpcastComparisons); - reg.register_late_lint_pass(box regex::Pass::default()); + reg.register_late_lint_pass(box regex::Regex::default()); reg.register_late_lint_pass(box copies::CopyAndPaste); reg.register_late_lint_pass(box copy_iterator::CopyIterator); - reg.register_late_lint_pass(box format::Pass); + reg.register_late_lint_pass(box format::UselessFormat); reg.register_early_lint_pass(box formatting::Formatting); reg.register_late_lint_pass(box swap::Swap); reg.register_early_lint_pass(box if_not_else::IfNotElse); @@ -505,11 +510,11 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_late_lint_pass(box overflow_check_conditional::OverflowCheckConditional); reg.register_late_lint_pass(box unused_label::UnusedLabel); reg.register_late_lint_pass(box new_without_default::NewWithoutDefault::default()); - reg.register_late_lint_pass(box blacklisted_name::BlackListedName::new( + reg.register_late_lint_pass(box blacklisted_name::BlacklistedName::new( conf.blacklisted_names.iter().cloned().collect() )); reg.register_late_lint_pass(box functions::Functions::new(conf.too_many_arguments_threshold, conf.too_many_lines_threshold)); - reg.register_early_lint_pass(box doc::Doc::new(conf.doc_valid_idents.iter().cloned().collect())); + reg.register_early_lint_pass(box doc::DocMarkdown::new(conf.doc_valid_idents.iter().cloned().collect())); reg.register_late_lint_pass(box neg_multiply::NegMultiply); reg.register_early_lint_pass(box unsafe_removed_from_name::UnsafeNameRemoval); reg.register_late_lint_pass(box mem_discriminant::MemDiscriminant); @@ -521,28 +526,28 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_late_lint_pass(box eval_order_dependence::EvalOrderDependence); reg.register_late_lint_pass(box missing_doc::MissingDoc::new()); reg.register_late_lint_pass(box missing_inline::MissingInline); - reg.register_late_lint_pass(box ok_if_let::Pass); - reg.register_late_lint_pass(box redundant_pattern_matching::Pass); - reg.register_late_lint_pass(box partialeq_ne_impl::Pass); - reg.register_early_lint_pass(box reference::Pass); - reg.register_early_lint_pass(box reference::DerefPass); + reg.register_late_lint_pass(box ok_if_let::OkIfLet); + reg.register_late_lint_pass(box redundant_pattern_matching::RedundantPatternMatching); + reg.register_late_lint_pass(box partialeq_ne_impl::PartialEqNeImpl); + reg.register_early_lint_pass(box reference::DerefAddrOf); + reg.register_early_lint_pass(box reference::RefInDeref); reg.register_early_lint_pass(box double_parens::DoubleParens); reg.register_late_lint_pass(box unused_io_amount::UnusedIoAmount); reg.register_late_lint_pass(box large_enum_variant::LargeEnumVariant::new(conf.enum_variant_size_threshold)); - reg.register_late_lint_pass(box explicit_write::Pass); + reg.register_late_lint_pass(box explicit_write::ExplicitWrite); reg.register_late_lint_pass(box needless_pass_by_value::NeedlessPassByValue); reg.register_late_lint_pass(box trivially_copy_pass_by_ref::TriviallyCopyPassByRef::new( conf.trivial_copy_size_limit, ®.sess.target, )); reg.register_early_lint_pass(box literal_representation::LiteralDigitGrouping); - reg.register_early_lint_pass(box literal_representation::LiteralRepresentation::new( + reg.register_early_lint_pass(box literal_representation::DecimalLiteralRepresentation::new( conf.literal_representation_threshold )); reg.register_late_lint_pass(box use_self::UseSelf); reg.register_late_lint_pass(box bytecount::ByteCount); - reg.register_late_lint_pass(box infinite_iter::Pass); - reg.register_late_lint_pass(box inline_fn_without_body::Pass); + reg.register_late_lint_pass(box infinite_iter::InfiniteIter); + reg.register_late_lint_pass(box inline_fn_without_body::InlineFnWithoutBody); reg.register_late_lint_pass(box invalid_ref::InvalidRef); reg.register_late_lint_pass(box identity_conversion::IdentityConversion::default()); reg.register_late_lint_pass(box types::ImplicitHasher); @@ -550,28 +555,29 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_late_lint_pass(box fallible_impl_from::FallibleImplFrom); reg.register_late_lint_pass(box replace_consts::ReplaceConsts); reg.register_late_lint_pass(box types::UnitArg); - reg.register_late_lint_pass(box double_comparison::Pass); - reg.register_late_lint_pass(box question_mark::Pass); + reg.register_late_lint_pass(box double_comparison::DoubleComparisons); + reg.register_late_lint_pass(box question_mark::QuestionMark); reg.register_late_lint_pass(box suspicious_trait_impl::SuspiciousImpl); - reg.register_early_lint_pass(box cargo_common_metadata::Pass); - reg.register_early_lint_pass(box multiple_crate_versions::Pass); - reg.register_early_lint_pass(box wildcard_dependencies::Pass); - reg.register_late_lint_pass(box map_unit_fn::Pass); - reg.register_late_lint_pass(box infallible_destructuring_match::Pass); - reg.register_late_lint_pass(box inherent_impl::Pass::default()); + reg.register_early_lint_pass(box cargo_common_metadata::CargoCommonMetadata); + reg.register_early_lint_pass(box multiple_crate_versions::MultipleCrateVersions); + reg.register_early_lint_pass(box wildcard_dependencies::WildcardDependencies); + reg.register_late_lint_pass(box map_unit_fn::MapUnit); + reg.register_late_lint_pass(box infallible_destructuring_match::InfallibleDestructingMatch); + reg.register_late_lint_pass(box inherent_impl::MultipleInherentImpl::default()); reg.register_late_lint_pass(box neg_cmp_op_on_partial_ord::NoNegCompOpForPartialOrd); - reg.register_late_lint_pass(box unwrap::Pass); + reg.register_late_lint_pass(box unwrap::Unwrap); reg.register_late_lint_pass(box duration_subsec::DurationSubsec); reg.register_late_lint_pass(box default_trait_access::DefaultTraitAccess); reg.register_late_lint_pass(box indexing_slicing::IndexingSlicing); reg.register_late_lint_pass(box non_copy_const::NonCopyConst); - reg.register_late_lint_pass(box ptr_offset_with_cast::Pass); + reg.register_late_lint_pass(box ptr_offset_with_cast::PtrOffsetWithCast); reg.register_late_lint_pass(box redundant_clone::RedundantClone); - reg.register_late_lint_pass(box slow_vector_initialization::Pass); + reg.register_late_lint_pass(box slow_vector_initialization::SlowVectorInit); reg.register_late_lint_pass(box types::RefToMut); reg.register_late_lint_pass(box assertions_on_constants::AssertionsOnConstants); reg.register_late_lint_pass(box missing_const_for_fn::MissingConstForFn); - reg.register_late_lint_pass(box transmuting_null::Pass); + reg.register_late_lint_pass(box transmuting_null::TransmutingNull); + reg.register_late_lint_pass(box path_buf_push_overwrite::PathBufPushOverwrite); reg.register_lint_group("clippy::restriction", Some("clippy_restriction"), vec![ arithmetic::FLOAT_ARITHMETIC, @@ -647,7 +653,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_lint_group("clippy::internal", Some("clippy_internal"), vec![ utils::internal_lints::CLIPPY_LINTS_INTERNAL, utils::internal_lints::COMPILER_LINT_FUNCTIONS, - utils::internal_lints::DEFAULT_HASH_TYPES, utils::internal_lints::LINT_WITHOUT_LINT_PASS, ]); @@ -1122,6 +1127,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { missing_const_for_fn::MISSING_CONST_FOR_FN, mutex_atomic::MUTEX_INTEGER, needless_borrow::NEEDLESS_BORROW, + path_buf_push_overwrite::PATH_BUF_PUSH_OVERWRITE, redundant_clone::REDUNDANT_CLONE, unwrap::PANICKING_UNWRAP, unwrap::UNNECESSARY_UNWRAP, diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index cd717e586e71..60b243784ee6 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -3,7 +3,7 @@ use rustc::hir::def::Def; use rustc::hir::intravisit::*; use rustc::hir::*; use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use syntax::source_map::Span; use syntax::symbol::keywords; @@ -55,20 +55,9 @@ declare_clippy_lint! { "unused lifetimes in function definitions" } -#[derive(Copy, Clone)] -pub struct LifetimePass; +declare_lint_pass!(Lifetimes => [NEEDLESS_LIFETIMES, EXTRA_UNUSED_LIFETIMES]); -impl LintPass for LifetimePass { - fn get_lints(&self) -> LintArray { - lint_array!(NEEDLESS_LIFETIMES, EXTRA_UNUSED_LIFETIMES) - } - - fn name(&self) -> &'static str { - "LifeTimes" - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LifetimePass { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Lifetimes { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { if let ItemKind::Fn(ref decl, _, ref generics, id) = item.node { check_fn_inner(cx, decl, Some(id), generics, item.span); diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index e97845314f9d..004e9f14b580 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -4,7 +4,7 @@ use crate::utils::{snippet_opt, span_lint_and_sugg}; use if_chain::if_chain; use rustc::lint::{in_external_macro, EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint, impl_lint_pass}; use rustc_errors::Applicability; use syntax::ast::*; use syntax_pos; @@ -334,23 +334,12 @@ impl WarningType { } } -#[derive(Copy, Clone)] -pub struct LiteralDigitGrouping; - -impl LintPass for LiteralDigitGrouping { - fn get_lints(&self) -> LintArray { - lint_array!( - UNREADABLE_LITERAL, - INCONSISTENT_DIGIT_GROUPING, - LARGE_DIGIT_GROUPS, - MISTYPED_LITERAL_SUFFIXES, - ) - } - - fn name(&self) -> &'static str { - "LiteralDigitGrouping" - } -} +declare_lint_pass!(LiteralDigitGrouping => [ + UNREADABLE_LITERAL, + INCONSISTENT_DIGIT_GROUPING, + LARGE_DIGIT_GROUPS, + MISTYPED_LITERAL_SUFFIXES, +]); impl EarlyLintPass for LiteralDigitGrouping { fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { @@ -488,22 +477,15 @@ impl LiteralDigitGrouping { } } +#[allow(clippy::module_name_repetitions)] #[derive(Copy, Clone)] -pub struct LiteralRepresentation { +pub struct DecimalLiteralRepresentation { threshold: u64, } -impl LintPass for LiteralRepresentation { - fn get_lints(&self) -> LintArray { - lint_array!(DECIMAL_LITERAL_REPRESENTATION) - } - - fn name(&self) -> &'static str { - "DecimalLiteralRepresentation" - } -} +impl_lint_pass!(DecimalLiteralRepresentation => [DECIMAL_LITERAL_REPRESENTATION]); -impl EarlyLintPass for LiteralRepresentation { +impl EarlyLintPass for DecimalLiteralRepresentation { fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { if in_external_macro(cx.sess(), expr.span) { return; @@ -515,7 +497,7 @@ impl EarlyLintPass for LiteralRepresentation { } } -impl LiteralRepresentation { +impl DecimalLiteralRepresentation { pub fn new(threshold: u64) -> Self { Self { threshold } } diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index a070e824cc0d..a38ce24d11ce 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -7,7 +7,7 @@ use rustc::hir::intravisit::{walk_block, walk_expr, walk_pat, walk_stmt, NestedV use rustc::hir::*; use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass}; use rustc::middle::region; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; // use rustc::middle::region::CodeExtent; use crate::consts::{constant, Constant}; use crate::utils::usage::mutated_variables; @@ -439,39 +439,28 @@ declare_clippy_lint! { "variables used within while expression are not mutated in the body" } -#[derive(Copy, Clone)] -pub struct Pass; - -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!( - MANUAL_MEMCPY, - NEEDLESS_RANGE_LOOP, - EXPLICIT_ITER_LOOP, - EXPLICIT_INTO_ITER_LOOP, - ITER_NEXT_LOOP, - FOR_LOOP_OVER_RESULT, - FOR_LOOP_OVER_OPTION, - WHILE_LET_LOOP, - UNUSED_COLLECT, - NEEDLESS_COLLECT, - REVERSE_RANGE_LOOP, - EXPLICIT_COUNTER_LOOP, - EMPTY_LOOP, - WHILE_LET_ON_ITERATOR, - FOR_KV_MAP, - NEVER_LOOP, - MUT_RANGE_BOUND, - WHILE_IMMUTABLE_CONDITION, - ) - } - - fn name(&self) -> &'static str { - "Loops" - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { +declare_lint_pass!(Loops => [ + MANUAL_MEMCPY, + NEEDLESS_RANGE_LOOP, + EXPLICIT_ITER_LOOP, + EXPLICIT_INTO_ITER_LOOP, + ITER_NEXT_LOOP, + FOR_LOOP_OVER_RESULT, + FOR_LOOP_OVER_OPTION, + WHILE_LET_LOOP, + UNUSED_COLLECT, + NEEDLESS_COLLECT, + REVERSE_RANGE_LOOP, + EXPLICIT_COUNTER_LOOP, + EMPTY_LOOP, + WHILE_LET_ON_ITERATOR, + FOR_KV_MAP, + NEVER_LOOP, + MUT_RANGE_BOUND, + WHILE_IMMUTABLE_CONDITION, +]); + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Loops { #[allow(clippy::too_many_lines)] fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { // we don't want to check expanded macros @@ -530,12 +519,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { return; } - // NOTE: we used to make build a body here instead of using + // NOTE: we used to build a body here instead of using // ellipsis, this was removed because: // 1) it was ugly with big bodies; // 2) it was not indented properly; // 3) it wasn’t very smart (see #675). - let mut applicability = Applicability::MachineApplicable; + let mut applicability = Applicability::HasPlaceholders; span_lint_and_sugg( cx, WHILE_LET_LOOP, @@ -2404,7 +2393,8 @@ impl<'a, 'tcx> VarCollectorVisitor<'a, 'tcx> { Def::Local(node_id) | Def::Upvar(node_id, ..) => { self.ids.insert(node_id); }, - Def::Static(def_id, mutable) => { + Def::Static(def_id) => { + let mutable = self.cx.tcx.is_mutable_static(def_id); self.def_ids.insert(def_id, mutable); }, _ => {}, diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index 4a3092640962..4743dec9d5c2 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -1,19 +1,16 @@ use crate::utils::paths; use crate::utils::{ - in_macro, match_trait_method, match_type, remove_blocks, snippet_with_applicability, span_lint_and_sugg, + in_macro, is_copy, match_trait_method, match_type, remove_blocks, snippet_with_applicability, span_lint_and_sugg, }; use if_chain::if_chain; use rustc::hir; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::ty; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; use syntax::ast::Ident; use syntax::source_map::Span; -#[derive(Clone)] -pub struct Pass; - declare_clippy_lint! { /// **What it does:** Checks for usage of `iterator.map(|x| x.clone())` and suggests /// `iterator.cloned()` instead @@ -42,17 +39,9 @@ declare_clippy_lint! { "using `iterator.map(|x| x.clone())`, or dereferencing closures for `Copy` types" } -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(MAP_CLONE) - } - - fn name(&self) -> &'static str { - "MapClone" - } -} +declare_lint_pass!(MapClone => [MAP_CLONE]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MapClone { fn check_expr(&mut self, cx: &LateContext<'_, '_>, e: &hir::Expr) { if in_macro(e.span) { return; @@ -63,7 +52,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if args.len() == 2; if method.ident.as_str() == "map"; let ty = cx.tables.expr_ty(&args[0]); - if match_type(cx, ty, &paths::OPTION) || match_trait_method(cx, e, &paths::ITERATOR); + let is_option = match_type(cx, ty, &paths::OPTION); + if is_option || match_trait_method(cx, e, &paths::ITERATOR); if let hir::ExprKind::Closure(_, _, body_id, _, _) = args[1].node; let closure_body = cx.tcx.hir().body(body_id); let closure_expr = remove_blocks(&closure_body.value); @@ -73,14 +63,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { hir::BindingAnnotation::Unannotated, .., name, None ) = inner.node { if ident_eq(name, closure_expr) { - lint(cx, e.span, args[0].span); + // FIXME When Iterator::copied() stabilizes we can remove is_option + // from here and the other lint() calls + lint(cx, e.span, args[0].span, is_option); } }, hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, .., name, None) => { match closure_expr.node { hir::ExprKind::Unary(hir::UnOp::UnDeref, ref inner) => { if ident_eq(name, inner) && !cx.tables.expr_ty(inner).is_box() { - lint(cx, e.span, args[0].span); + lint(cx, e.span, args[0].span, is_option); } }, hir::ExprKind::MethodCall(ref method, _, ref obj) => { @@ -88,8 +80,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { && match_trait_method(cx, closure_expr, &paths::CLONE_TRAIT) { let obj_ty = cx.tables.expr_ty(&obj[0]); - if let ty::Ref(..) = obj_ty.sty { - lint(cx, e.span, args[0].span); + if let ty::Ref(_, ty, _) = obj_ty.sty { + let copy = is_copy(cx, ty); + lint(cx, e.span, args[0].span, is_option && copy); } else { lint_needless_cloning(cx, e.span, args[0].span); } @@ -125,18 +118,33 @@ fn lint_needless_cloning(cx: &LateContext<'_, '_>, root: Span, receiver: Span) { ) } -fn lint(cx: &LateContext<'_, '_>, replace: Span, root: Span) { +fn lint(cx: &LateContext<'_, '_>, replace: Span, root: Span, copied: bool) { let mut applicability = Applicability::MachineApplicable; - span_lint_and_sugg( - cx, - MAP_CLONE, - replace, - "You are using an explicit closure for cloning elements", - "Consider calling the dedicated `cloned` method", - format!( - "{}.cloned()", - snippet_with_applicability(cx, root, "..", &mut applicability) - ), - applicability, - ) + if copied { + span_lint_and_sugg( + cx, + MAP_CLONE, + replace, + "You are using an explicit closure for copying elements", + "Consider calling the dedicated `copied` method", + format!( + "{}.copied()", + snippet_with_applicability(cx, root, "..", &mut applicability) + ), + applicability, + ) + } else { + span_lint_and_sugg( + cx, + MAP_CLONE, + replace, + "You are using an explicit closure for cloning elements", + "Consider calling the dedicated `cloned` method", + format!( + "{}.cloned()", + snippet_with_applicability(cx, root, "..", &mut applicability) + ), + applicability, + ) + } } diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs index 22c336b8c478..eae43cfa8240 100644 --- a/clippy_lints/src/map_unit_fn.rs +++ b/clippy_lints/src/map_unit_fn.rs @@ -4,13 +4,10 @@ use if_chain::if_chain; use rustc::hir; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::ty::{self, Ty}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; use syntax::source_map::Span; -#[derive(Clone)] -pub struct Pass; - declare_clippy_lint! { /// **What it does:** Checks for usage of `option.map(f)` where f is a function /// or closure that returns the unit type. @@ -77,15 +74,7 @@ declare_clippy_lint! { "using `result.map(f)`, where f is a function or closure that returns ()" } -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(OPTION_MAP_UNIT_FN, RESULT_MAP_UNIT_FN) - } - - fn name(&self) -> &'static str { - "MapUnit" - } -} +declare_lint_pass!(MapUnit => [OPTION_MAP_UNIT_FN, RESULT_MAP_UNIT_FN]); fn is_unit_type(ty: Ty<'_>) -> bool { match ty.sty { @@ -249,7 +238,7 @@ fn lint_map_unit_fn(cx: &LateContext<'_, '_>, stmt: &hir::Stmt, expr: &hir::Expr } } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MapUnit { fn check_stmt(&mut self, cx: &LateContext<'_, '_>, stmt: &hir::Stmt) { if in_macro(stmt.span) { return; diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 34cb2422e1c5..bcd3119b7bc5 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -9,8 +9,8 @@ use if_chain::if_chain; use rustc::hir::def::CtorKind; use rustc::hir::*; use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass}; -use rustc::ty::{self, Ty, TyKind}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::ty::{self, Ty}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; use std::cmp::Ordering; use std::collections::Bound; @@ -215,29 +215,18 @@ declare_clippy_lint! { "a wildcard enum match arm using `_`" } -#[allow(missing_copy_implementations)] -pub struct MatchPass; - -impl LintPass for MatchPass { - fn get_lints(&self) -> LintArray { - lint_array!( - SINGLE_MATCH, - MATCH_REF_PATS, - MATCH_BOOL, - SINGLE_MATCH_ELSE, - MATCH_OVERLAPPING_ARM, - MATCH_WILD_ERR_ARM, - MATCH_AS_REF, - WILDCARD_ENUM_MATCH_ARM - ) - } - - fn name(&self) -> &'static str { - "Matches" - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MatchPass { +declare_lint_pass!(Matches => [ + SINGLE_MATCH, + MATCH_REF_PATS, + MATCH_BOOL, + SINGLE_MATCH_ELSE, + MATCH_OVERLAPPING_ARM, + MATCH_WILD_ERR_ARM, + MATCH_AS_REF, + WILDCARD_ENUM_MATCH_ARM +]); + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Matches { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if in_external_macro(cx.sess(), expr.span) { return; @@ -500,7 +489,7 @@ fn check_wild_enum_match(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm]) { // already covered. let mut missing_variants = vec![]; - if let TyKind::Adt(def, _) = ty.sty { + if let ty::Adt(def, _) = ty.sty { for variant in &def.variants { missing_variants.push(variant); } diff --git a/clippy_lints/src/mem_discriminant.rs b/clippy_lints/src/mem_discriminant.rs index 0eb42dbaaf99..002892903873 100644 --- a/clippy_lints/src/mem_discriminant.rs +++ b/clippy_lints/src/mem_discriminant.rs @@ -1,8 +1,8 @@ -use crate::utils::{match_def_path, paths, snippet, span_lint_and_then, walk_ptrs_ty_depth}; +use crate::utils::{paths, snippet, span_lint_and_then, walk_ptrs_ty_depth}; 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 rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; use std::iter; @@ -27,17 +27,7 @@ declare_clippy_lint! { "calling mem::descriminant on non-enum type" } -pub struct MemDiscriminant; - -impl LintPass for MemDiscriminant { - fn get_lints(&self) -> LintArray { - lint_array![MEM_DISCRIMINANT_NON_ENUM] - } - - fn name(&self) -> &'static str { - "MemDiscriminant" - } -} +declare_lint_pass!(MemDiscriminant => [MEM_DISCRIMINANT_NON_ENUM]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MemDiscriminant { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { @@ -46,7 +36,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MemDiscriminant { // is `mem::discriminant` if let ExprKind::Path(ref func_qpath) = func.node; if let Some(def_id) = cx.tables.qpath_def(func_qpath, func.hir_id).opt_def_id(); - if match_def_path(cx.tcx, def_id, &paths::MEM_DISCRIMINANT); + if cx.match_def_path(def_id, &paths::MEM_DISCRIMINANT); // type is non-enum let ty_param = cx.tables.node_substs(func.hir_id).type_at(0); if !ty_param.is_enum(); diff --git a/clippy_lints/src/mem_forget.rs b/clippy_lints/src/mem_forget.rs index 82070063b046..4fabfac0ab65 100644 --- a/clippy_lints/src/mem_forget.rs +++ b/clippy_lints/src/mem_forget.rs @@ -1,7 +1,7 @@ -use crate::utils::{match_def_path, paths, span_lint}; +use crate::utils::{paths, span_lint}; use rustc::hir::{Expr, ExprKind}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { /// **What it does:** Checks for usage of `std::mem::forget(t)` where `t` is @@ -21,24 +21,14 @@ declare_clippy_lint! { "`mem::forget` usage on `Drop` types, likely to cause memory leaks" } -pub struct MemForget; - -impl LintPass for MemForget { - fn get_lints(&self) -> LintArray { - lint_array![MEM_FORGET] - } - - fn name(&self) -> &'static str { - "MemForget" - } -} +declare_lint_pass!(MemForget => [MEM_FORGET]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MemForget { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { if let ExprKind::Call(ref path_expr, ref args) = e.node { if let ExprKind::Path(ref qpath) = path_expr.node { if let Some(def_id) = cx.tables.qpath_def(qpath, path_expr.hir_id).opt_def_id() { - if match_def_path(cx.tcx, def_id, &paths::MEM_FORGET) { + if cx.match_def_path(def_id, &paths::MEM_FORGET) { let forgot_ty = cx.tables.expr_ty(&args[0]); if forgot_ty.ty_adt_def().map_or(false, |def| def.has_dtor(cx.tcx)) { diff --git a/clippy_lints/src/mem_replace.rs b/clippy_lints/src/mem_replace.rs index 57b05ab108cb..49d0a6de229a 100644 --- a/clippy_lints/src/mem_replace.rs +++ b/clippy_lints/src/mem_replace.rs @@ -1,8 +1,8 @@ -use crate::utils::{match_def_path, match_qpath, paths, snippet_with_applicability, span_lint_and_sugg}; +use crate::utils::{match_qpath, paths, snippet_with_applicability, span_lint_and_sugg}; use if_chain::if_chain; use rustc::hir::{Expr, ExprKind, MutMutable, QPath}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; declare_clippy_lint! { @@ -32,17 +32,7 @@ declare_clippy_lint! { "replacing an `Option` with `None` instead of `take()`" } -pub struct MemReplace; - -impl LintPass for MemReplace { - fn get_lints(&self) -> LintArray { - lint_array![MEM_REPLACE_OPTION_WITH_NONE] - } - - fn name(&self) -> &'static str { - "MemReplace" - } -} +declare_lint_pass!(MemReplace => [MEM_REPLACE_OPTION_WITH_NONE]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MemReplace { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { @@ -52,7 +42,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MemReplace { if func_args.len() == 2; if let ExprKind::Path(ref func_qpath) = func.node; if let Some(def_id) = cx.tables.qpath_def(func_qpath, func.hir_id).opt_def_id(); - if match_def_path(cx.tcx, def_id, &paths::MEM_REPLACE); + if cx.match_def_path(def_id, &paths::MEM_REPLACE); // Check that second argument is `Option::None` if let ExprKind::Path(ref replacement_qpath) = func_args[1].node; diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index bccabe1a61d8..d8595ea9004c 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -11,7 +11,7 @@ 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::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; use syntax::ast; use syntax::source_map::{BytePos, Span}; @@ -20,16 +20,13 @@ use syntax::symbol::LocalInternedString; use crate::utils::paths; use crate::utils::sugg; use crate::utils::{ - get_arg_name, get_parent_expr, get_trait_def_id, has_iter_method, implements_trait, in_macro, is_copy, is_expn_of, - is_self, is_self_ty, iter_input_pats, last_path_segment, match_def_path, match_path, match_qpath, + get_arg_name, get_parent_expr, get_trait_def_id, has_iter_method, implements_trait, in_macro, is_copy, + is_ctor_function, is_expn_of, is_self, is_self_ty, iter_input_pats, last_path_segment, match_path, match_qpath, match_trait_method, match_type, match_var, method_calls, method_chain_args, remove_blocks, return_ty, same_tys, 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, }; -#[derive(Clone)] -pub struct Pass; - declare_clippy_lint! { /// **What it does:** Checks for `.unwrap()` calls on `Option`s. /// @@ -362,7 +359,7 @@ declare_clippy_lint! { /// **Why is this bad?** The function will always be called. /// /// **Known problems:** If the function has side-effects, not calling it will - /// change the semantic of the program, but you shouldn't rely on that anyway. + /// change the semantics of the program, but you shouldn't rely on that anyway. /// /// **Example:** /// ```rust @@ -777,52 +774,44 @@ declare_clippy_lint! { "using `.into_iter()` on a reference" } -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!( - OPTION_UNWRAP_USED, - RESULT_UNWRAP_USED, - SHOULD_IMPLEMENT_TRAIT, - WRONG_SELF_CONVENTION, - WRONG_PUB_SELF_CONVENTION, - OK_EXPECT, - OPTION_MAP_UNWRAP_OR, - OPTION_MAP_UNWRAP_OR_ELSE, - RESULT_MAP_UNWRAP_OR_ELSE, - OPTION_MAP_OR_NONE, - OR_FUN_CALL, - EXPECT_FUN_CALL, - CHARS_NEXT_CMP, - CHARS_LAST_CMP, - CLONE_ON_COPY, - CLONE_ON_REF_PTR, - CLONE_DOUBLE_REF, - NEW_RET_NO_SELF, - SINGLE_CHAR_PATTERN, - SEARCH_IS_SOME, - TEMPORARY_CSTRING_AS_PTR, - FILTER_NEXT, - FILTER_MAP, - MAP_FLATTEN, - ITER_NTH, - ITER_SKIP_NEXT, - GET_UNWRAP, - STRING_EXTEND_CHARS, - ITER_CLONED_COLLECT, - USELESS_ASREF, - UNNECESSARY_FOLD, - UNNECESSARY_FILTER_MAP, - INTO_ITER_ON_ARRAY, - INTO_ITER_ON_REF, - ) - } - - fn name(&self) -> &'static str { - "Methods" - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { +declare_lint_pass!(Methods => [ + OPTION_UNWRAP_USED, + RESULT_UNWRAP_USED, + SHOULD_IMPLEMENT_TRAIT, + WRONG_SELF_CONVENTION, + WRONG_PUB_SELF_CONVENTION, + OK_EXPECT, + OPTION_MAP_UNWRAP_OR, + OPTION_MAP_UNWRAP_OR_ELSE, + RESULT_MAP_UNWRAP_OR_ELSE, + OPTION_MAP_OR_NONE, + OR_FUN_CALL, + EXPECT_FUN_CALL, + CHARS_NEXT_CMP, + CHARS_LAST_CMP, + CLONE_ON_COPY, + CLONE_ON_REF_PTR, + CLONE_DOUBLE_REF, + NEW_RET_NO_SELF, + SINGLE_CHAR_PATTERN, + SEARCH_IS_SOME, + TEMPORARY_CSTRING_AS_PTR, + FILTER_NEXT, + FILTER_MAP, + MAP_FLATTEN, + ITER_NTH, + ITER_SKIP_NEXT, + GET_UNWRAP, + STRING_EXTEND_CHARS, + ITER_CLONED_COLLECT, + USELESS_ASREF, + UNNECESSARY_FOLD, + UNNECESSARY_FILTER_MAP, + INTO_ITER_ON_ARRAY, + INTO_ITER_ON_REF, +]); + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods { #[allow(clippy::cognitive_complexity)] fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) { if in_macro(expr.span) { @@ -1083,6 +1072,11 @@ fn lint_or_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: Spa return; } + // ignore enum and struct constructors + if is_ctor_function(cx, &arg) { + return; + } + // don't lint for constant values let owner_def = cx.tcx.hir().get_parent_did_by_hir_id(arg.hir_id); let promotable = cx.tcx.rvalue_promotable_map(owner_def).contains(&arg.hir_id.local_id); @@ -1464,7 +1458,7 @@ fn lint_cstring_as_ptr(cx: &LateContext<'_, '_>, expr: &hir::Expr, new: &hir::Ex if args.len() == 1; if let hir::ExprKind::Path(ref path) = fun.node; if let Def::Method(did) = cx.tables.qpath_def(path, fun.hir_id); - if match_def_path(cx.tcx, did, &paths::CSTRING_NEW); + if cx.match_def_path(did, &paths::CSTRING_NEW); then { span_lint_and_then( cx, diff --git a/clippy_lints/src/minmax.rs b/clippy_lints/src/minmax.rs index 8633458626a1..b5c064869a42 100644 --- a/clippy_lints/src/minmax.rs +++ b/clippy_lints/src/minmax.rs @@ -1,8 +1,8 @@ use crate::consts::{constant_simple, Constant}; -use crate::utils::{match_def_path, paths, span_lint}; +use crate::utils::{paths, span_lint}; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use std::cmp::Ordering; declare_clippy_lint! { @@ -25,17 +25,7 @@ declare_clippy_lint! { "`min(_, max(_, _))` (or vice versa) with bounds clamping the result to a constant" } -pub struct MinMaxPass; - -impl LintPass for MinMaxPass { - fn get_lints(&self) -> LintArray { - lint_array!(MIN_MAX) - } - - fn name(&self) -> &'static str { - "MinMax" - } -} +declare_lint_pass!(MinMaxPass => [MIN_MAX]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MinMaxPass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { @@ -73,9 +63,9 @@ fn min_max<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr) -> Option<(MinMax, Cons if let ExprKind::Call(ref path, ref args) = expr.node { if let ExprKind::Path(ref qpath) = path.node { cx.tables.qpath_def(qpath, path.hir_id).opt_def_id().and_then(|def_id| { - if match_def_path(cx.tcx, def_id, &paths::CMP_MIN) { + if cx.match_def_path(def_id, &paths::CMP_MIN) { fetch_const(cx, args, MinMax::Min) - } else if match_def_path(cx.tcx, def_id, &paths::CMP_MAX) { + } else if cx.match_def_path(def_id, &paths::CMP_MAX) { fetch_const(cx, args, MinMax::Max) } else { None diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index bd0b4bd4515a..6e41249ea648 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -4,7 +4,7 @@ use rustc::hir::intravisit::FnKind; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::ty; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; use syntax::ast::LitKind; use syntax::source_map::{ExpnFormat, Span}; @@ -13,8 +13,8 @@ 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, + last_path_segment, match_qpath, match_trait_method, paths, snippet, span_lint, span_lint_and_then, + span_lint_hir_and_then, walk_ptrs_ty, SpanlessEq, }; declare_clippy_lint! { @@ -232,31 +232,20 @@ declare_clippy_lint! { "using `==` or `!=` on float constants instead of comparing difference with an epsilon" } -#[derive(Copy, Clone)] -pub struct Pass; - -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!( - TOPLEVEL_REF_ARG, - CMP_NAN, - FLOAT_CMP, - CMP_OWNED, - MODULO_ONE, - REDUNDANT_PATTERN, - USED_UNDERSCORE_BINDING, - SHORT_CIRCUIT_STATEMENT, - ZERO_PTR, - FLOAT_CMP_CONST - ) - } - - fn name(&self) -> &'static str { - "MiscLints" - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { +declare_lint_pass!(MiscLints => [ + TOPLEVEL_REF_ARG, + CMP_NAN, + FLOAT_CMP, + CMP_OWNED, + MODULO_ONE, + REDUNDANT_PATTERN, + USED_UNDERSCORE_BINDING, + SHORT_CIRCUIT_STATEMENT, + ZERO_PTR, + FLOAT_CMP_CONST +]); + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MiscLints { fn check_fn( &mut self, cx: &LateContext<'a, 'tcx>, @@ -293,19 +282,20 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if let Some(ref init) = l.init; then { if an == BindingAnnotation::Ref || an == BindingAnnotation::RefMut { - let init = Sugg::hir(cx, init, ".."); + let sugg_init = Sugg::hir(cx, init, ".."); let (mutopt,initref) = if an == BindingAnnotation::RefMut { - ("mut ", init.mut_addr()) + ("mut ", sugg_init.mut_addr()) } else { - ("", init.addr()) + ("", sugg_init.addr()) }; let tyopt = if let Some(ref ty) = l.ty { format!(": &{mutopt}{ty}", mutopt=mutopt, ty=snippet(cx, ty.span, "_")) } else { String::new() }; - span_lint_and_then(cx, + span_lint_hir_and_then(cx, TOPLEVEL_REF_ARG, + init.hir_id, l.pat.span, "`ref` on an entire `let` pattern is discouraged, take a reference with `&` instead", |db| { diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index 3d41195f3496..c2e42a0a9933 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -1,7 +1,7 @@ use crate::utils::{constants, snippet, snippet_opt, span_help_and_lint, span_lint, span_lint_and_then}; use if_chain::if_chain; use rustc::lint::{in_external_macro, EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::Applicability; use std::char; @@ -172,27 +172,16 @@ declare_clippy_lint! { "shadowing a builtin type" } -#[derive(Copy, Clone)] -pub struct MiscEarly; - -impl LintPass for MiscEarly { - fn get_lints(&self) -> LintArray { - lint_array!( - UNNEEDED_FIELD_PATTERN, - DUPLICATE_UNDERSCORE_ARGUMENT, - REDUNDANT_CLOSURE_CALL, - DOUBLE_NEG, - MIXED_CASE_HEX_LITERALS, - UNSEPARATED_LITERAL_SUFFIX, - ZERO_PREFIXED_LITERAL, - BUILTIN_TYPE_SHADOW - ) - } - - fn name(&self) -> &'static str { - "MiscEarlyLints" - } -} +declare_lint_pass!(MiscEarlyLints => [ + UNNEEDED_FIELD_PATTERN, + DUPLICATE_UNDERSCORE_ARGUMENT, + REDUNDANT_CLOSURE_CALL, + DOUBLE_NEG, + MIXED_CASE_HEX_LITERALS, + UNSEPARATED_LITERAL_SUFFIX, + ZERO_PREFIXED_LITERAL, + BUILTIN_TYPE_SHADOW +]); // Used to find `return` statements or equivalents e.g., `?` struct ReturnVisitor { @@ -217,7 +206,7 @@ impl<'ast> Visitor<'ast> for ReturnVisitor { } } -impl EarlyLintPass for MiscEarly { +impl EarlyLintPass for MiscEarlyLints { fn check_generics(&mut self, cx: &EarlyContext<'_>, gen: &Generics) { for param in &gen.params { if let GenericParamKind::Type { .. } = param.kind { @@ -234,7 +223,7 @@ impl EarlyLintPass for MiscEarly { } } - fn check_pat(&mut self, cx: &EarlyContext<'_>, pat: &Pat, _: &mut bool) { + fn check_pat(&mut self, cx: &EarlyContext<'_>, pat: &Pat) { if let PatKind::Struct(ref npat, ref pfields, _) = pat.node { let mut wilds = 0; let type_name = npat @@ -398,7 +387,7 @@ impl EarlyLintPass for MiscEarly { } } -impl MiscEarly { +impl MiscEarlyLints { fn check_lit(self, cx: &EarlyContext<'_>, lit: &Lit) { if_chain! { if let LitKind::Int(value, ..) = lit.node; diff --git a/clippy_lints/src/missing_const_for_fn.rs b/clippy_lints/src/missing_const_for_fn.rs index 5bc949a6688a..54f34d64eb50 100644 --- a/clippy_lints/src/missing_const_for_fn.rs +++ b/clippy_lints/src/missing_const_for_fn.rs @@ -3,7 +3,7 @@ use rustc::hir; use rustc::hir::intravisit::FnKind; use rustc::hir::{Body, Constness, FnDecl, HirId}; use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_mir::transform::qualify_min_const_fn::is_min_const_fn; use syntax_pos::Span; @@ -57,18 +57,7 @@ declare_clippy_lint! { "Lint functions definitions that could be made `const fn`" } -#[derive(Clone)] -pub struct MissingConstForFn; - -impl LintPass for MissingConstForFn { - fn get_lints(&self) -> LintArray { - lint_array!(MISSING_CONST_FOR_FN) - } - - fn name(&self) -> &'static str { - "MissingConstForFn" - } -} +declare_lint_pass!(MissingConstForFn => [MISSING_CONST_FOR_FN]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingConstForFn { fn check_fn( diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index 721cfd870201..5d51f41aab67 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -10,7 +10,7 @@ use if_chain::if_chain; use rustc::hir; use rustc::lint::{LateContext, LateLintPass, LintArray, LintContext, LintPass}; use rustc::ty; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_tool_lint, impl_lint_pass}; use syntax::ast::{self, MetaItem, MetaItemKind}; use syntax::attr; use syntax::source_map::Span; @@ -103,15 +103,7 @@ impl MissingDoc { } } -impl LintPass for MissingDoc { - fn get_lints(&self) -> LintArray { - lint_array![MISSING_DOCS_IN_PRIVATE_ITEMS] - } - - fn name(&self) -> &'static str { - "MissingDoc" - } -} +impl_lint_pass!(MissingDoc => [MISSING_DOCS_IN_PRIVATE_ITEMS]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { fn enter_lint_attrs(&mut self, _: &LateContext<'a, 'tcx>, attrs: &'tcx [ast::Attribute]) { diff --git a/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs index c6b1b7eaf517..2c887eb54d08 100644 --- a/clippy_lints/src/missing_inline.rs +++ b/clippy_lints/src/missing_inline.rs @@ -1,7 +1,7 @@ use crate::utils::span_lint; use rustc::hir; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use syntax::ast; use syntax::source_map::Span; @@ -56,8 +56,6 @@ declare_clippy_lint! { "detects missing #[inline] attribute for public callables (functions, trait methods, methods...)" } -pub struct MissingInline; - fn check_missing_inline_attrs(cx: &LateContext<'_, '_>, attrs: &[ast::Attribute], sp: Span, desc: &'static str) { let has_inline = attrs.iter().any(|a| a.check_name("inline")); if !has_inline { @@ -79,15 +77,7 @@ fn is_executable<'a, 'tcx>(cx: &LateContext<'a, 'tcx>) -> bool { }) } -impl LintPass for MissingInline { - fn get_lints(&self) -> LintArray { - lint_array![MISSING_INLINE_IN_PUBLIC_ITEMS] - } - - fn name(&self) -> &'static str { - "MissingInline" - } -} +declare_lint_pass!(MissingInline => [MISSING_INLINE_IN_PUBLIC_ITEMS]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, it: &'tcx hir::Item) { diff --git a/clippy_lints/src/multiple_crate_versions.rs b/clippy_lints/src/multiple_crate_versions.rs index 68293f58cadd..483d8944ecc6 100644 --- a/clippy_lints/src/multiple_crate_versions.rs +++ b/clippy_lints/src/multiple_crate_versions.rs @@ -2,7 +2,7 @@ use crate::utils::span_lint; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use syntax::{ast::*, source_map::DUMMY_SP}; use cargo_metadata; @@ -31,19 +31,9 @@ declare_clippy_lint! { "multiple versions of the same crate being used" } -pub struct Pass; +declare_lint_pass!(MultipleCrateVersions => [MULTIPLE_CRATE_VERSIONS]); -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(MULTIPLE_CRATE_VERSIONS) - } - - fn name(&self) -> &'static str { - "MultipleCrateVersions" - } -} - -impl EarlyLintPass for Pass { +impl EarlyLintPass for MultipleCrateVersions { fn check_crate(&mut self, cx: &EarlyContext<'_>, _: &Crate) { let metadata = if let Ok(metadata) = cargo_metadata::MetadataCommand::new().exec() { metadata diff --git a/clippy_lints/src/mut_mut.rs b/clippy_lints/src/mut_mut.rs index f37f72135033..3971346dd1eb 100644 --- a/clippy_lints/src/mut_mut.rs +++ b/clippy_lints/src/mut_mut.rs @@ -3,7 +3,7 @@ use rustc::hir; use rustc::hir::intravisit; use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass}; use rustc::ty; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { /// **What it does:** Checks for instances of `mut mut` references. @@ -23,18 +23,7 @@ declare_clippy_lint! { "usage of double-mut refs, e.g., `&mut &mut ...`" } -#[derive(Copy, Clone)] -pub struct MutMut; - -impl LintPass for MutMut { - fn get_lints(&self) -> LintArray { - lint_array!(MUT_MUT) - } - - fn name(&self) -> &'static str { - "MutMut" - } -} +declare_lint_pass!(MutMut => [MUT_MUT]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutMut { fn check_block(&mut self, cx: &LateContext<'a, 'tcx>, block: &'tcx hir::Block) { diff --git a/clippy_lints/src/mut_reference.rs b/clippy_lints/src/mut_reference.rs index 7333aa9f5897..9f356e7ca792 100644 --- a/clippy_lints/src/mut_reference.rs +++ b/clippy_lints/src/mut_reference.rs @@ -3,7 +3,7 @@ use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::ty::subst::Subst; use rustc::ty::{self, Ty}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { /// **What it does:** Detects giving a mutable reference to a function that only @@ -23,18 +23,7 @@ declare_clippy_lint! { "an argument passed as a mutable reference although the callee only demands an immutable reference" } -#[derive(Copy, Clone)] -pub struct UnnecessaryMutPassed; - -impl LintPass for UnnecessaryMutPassed { - fn get_lints(&self) -> LintArray { - lint_array!(UNNECESSARY_MUT_PASSED) - } - - fn name(&self) -> &'static str { - "UnneccessaryMutPassed" - } -} +declare_lint_pass!(UnnecessaryMutPassed => [UNNECESSARY_MUT_PASSED]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnecessaryMutPassed { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { diff --git a/clippy_lints/src/mutex_atomic.rs b/clippy_lints/src/mutex_atomic.rs index 6800e4295f57..3b9641b354f2 100644 --- a/clippy_lints/src/mutex_atomic.rs +++ b/clippy_lints/src/mutex_atomic.rs @@ -6,7 +6,7 @@ use crate::utils::{match_type, paths, span_lint}; use rustc::hir::Expr; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::ty::{self, Ty}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use syntax::ast; declare_clippy_lint! { @@ -49,19 +49,9 @@ declare_clippy_lint! { "using a mutex for an integer type" } -impl LintPass for MutexAtomic { - fn get_lints(&self) -> LintArray { - lint_array!(MUTEX_ATOMIC, MUTEX_INTEGER) - } - - fn name(&self) -> &'static str { - "Mutex" - } -} - -pub struct MutexAtomic; +declare_lint_pass!(Mutex => [MUTEX_ATOMIC, MUTEX_INTEGER]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutexAtomic { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Mutex { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { let ty = cx.tables.expr_ty(expr); if let ty::Adt(_, subst) = ty.sty { diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index 6e81ecac05fb..94febdbd8a79 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -6,7 +6,7 @@ use crate::utils::sugg::Sugg; use crate::utils::{in_macro, span_lint, span_lint_and_sugg}; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; use syntax::ast::LitKind; use syntax::source_map::Spanned; @@ -54,18 +54,7 @@ declare_clippy_lint! { "comparing a variable to a boolean, e.g., `if x == true` or `if x != true`" } -#[derive(Copy, Clone)] -pub struct NeedlessBool; - -impl LintPass for NeedlessBool { - fn get_lints(&self) -> LintArray { - lint_array!(NEEDLESS_BOOL) - } - - fn name(&self) -> &'static str { - "NeedlessBool" - } -} +declare_lint_pass!(NeedlessBool => [NEEDLESS_BOOL]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBool { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { @@ -138,18 +127,7 @@ fn parent_node_is_if_expr<'a, 'b>(expr: &Expr, cx: &LateContext<'a, 'b>) -> bool false } -#[derive(Copy, Clone)] -pub struct BoolComparison; - -impl LintPass for BoolComparison { - fn get_lints(&self) -> LintArray { - lint_array!(BOOL_COMPARISON) - } - - fn name(&self) -> &'static str { - "BoolComparison" - } -} +declare_lint_pass!(BoolComparison => [BOOL_COMPARISON]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoolComparison { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { diff --git a/clippy_lints/src/needless_borrow.rs b/clippy_lints/src/needless_borrow.rs index 59b4095f61ec..f32304478bb6 100644 --- a/clippy_lints/src/needless_borrow.rs +++ b/clippy_lints/src/needless_borrow.rs @@ -8,7 +8,7 @@ use rustc::hir::{BindingAnnotation, Expr, ExprKind, HirId, Item, MutImmutable, P use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::ty; use rustc::ty::adjustment::{Adjust, Adjustment}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_tool_lint, impl_lint_pass}; use rustc_errors::Applicability; declare_clippy_lint! { @@ -34,15 +34,7 @@ pub struct NeedlessBorrow { derived_item: Option, } -impl LintPass for NeedlessBorrow { - fn get_lints(&self) -> LintArray { - lint_array!(NEEDLESS_BORROW) - } - - fn name(&self) -> &'static str { - "NeedlessBorrow" - } -} +impl_lint_pass!(NeedlessBorrow => [NEEDLESS_BORROW]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrow { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { diff --git a/clippy_lints/src/needless_borrowed_ref.rs b/clippy_lints/src/needless_borrowed_ref.rs index 2c1f87c53e35..9de5e1a03890 100644 --- a/clippy_lints/src/needless_borrowed_ref.rs +++ b/clippy_lints/src/needless_borrowed_ref.rs @@ -6,7 +6,7 @@ use crate::utils::{in_macro, snippet, span_lint_and_then}; use if_chain::if_chain; use rustc::hir::{BindingAnnotation, MutImmutable, Pat, PatKind}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; declare_clippy_lint! { @@ -51,18 +51,7 @@ declare_clippy_lint! { "taking a needless borrowed reference" } -#[derive(Copy, Clone)] -pub struct NeedlessBorrowedRef; - -impl LintPass for NeedlessBorrowedRef { - fn get_lints(&self) -> LintArray { - lint_array!(NEEDLESS_BORROWED_REFERENCE) - } - - fn name(&self) -> &'static str { - "NeedlessBorrowedRef" - } -} +declare_lint_pass!(NeedlessBorrowedRef => [NEEDLESS_BORROWED_REFERENCE]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrowedRef { fn check_pat(&mut self, cx: &LateContext<'a, 'tcx>, pat: &'tcx Pat) { diff --git a/clippy_lints/src/needless_continue.rs b/clippy_lints/src/needless_continue.rs index e37e917ddec8..71eb89ae90c9 100644 --- a/clippy_lints/src/needless_continue.rs +++ b/clippy_lints/src/needless_continue.rs @@ -34,7 +34,7 @@ //! //! This lint is **warn** by default. use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use std::borrow::Cow; use syntax::ast; use syntax::source_map::{original_sp, DUMMY_SP}; @@ -106,18 +106,7 @@ declare_clippy_lint! { "`continue` statements that can be replaced by a rearrangement of code" } -#[derive(Copy, Clone)] -pub struct NeedlessContinue; - -impl LintPass for NeedlessContinue { - fn get_lints(&self) -> LintArray { - lint_array!(NEEDLESS_CONTINUE) - } - - fn name(&self) -> &'static str { - "NeedlessContinue" - } -} +declare_lint_pass!(NeedlessContinue => [NEEDLESS_CONTINUE]); impl EarlyLintPass for NeedlessContinue { fn check_expr(&mut self, ctx: &EarlyContext<'_>, expr: &ast::Expr) { diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 2300456d4c38..dee93f70819e 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -12,7 +12,7 @@ use rustc::middle::expr_use_visitor as euv; use rustc::middle::mem_categorization as mc; use rustc::traits; use rustc::ty::{self, RegionKind, TypeFoldable}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::Applicability; use rustc_target::spec::abi::Abi; @@ -50,17 +50,7 @@ declare_clippy_lint! { "functions taking arguments by value, but not consuming them in its body" } -pub struct NeedlessPassByValue; - -impl LintPass for NeedlessPassByValue { - fn get_lints(&self) -> LintArray { - lint_array![NEEDLESS_PASS_BY_VALUE] - } - - fn name(&self) -> &'static str { - "NeedlessPassByValue" - } -} +declare_lint_pass!(NeedlessPassByValue => [NEEDLESS_PASS_BY_VALUE]); macro_rules! need { ($e: expr) => { diff --git a/clippy_lints/src/needless_update.rs b/clippy_lints/src/needless_update.rs index 2ce9bf78aa6c..316395acf263 100644 --- a/clippy_lints/src/needless_update.rs +++ b/clippy_lints/src/needless_update.rs @@ -2,7 +2,7 @@ use crate::utils::span_lint; use rustc::hir::{Expr, ExprKind}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::ty; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { /// **What it does:** Checks for needlessly including a base struct on update @@ -26,20 +26,9 @@ declare_clippy_lint! { "using `Foo { ..base }` when there are no missing fields" } -#[derive(Copy, Clone)] -pub struct Pass; +declare_lint_pass!(NeedlessUpdate => [NEEDLESS_UPDATE]); -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(NEEDLESS_UPDATE) - } - - fn name(&self) -> &'static str { - "NeedUpdate" - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessUpdate { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if let ExprKind::Struct(_, ref fields, Some(ref base)) = expr.node { let ty = cx.tables.expr_ty(expr); diff --git a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs index 7b074f438f4b..e05a953b3060 100644 --- a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs +++ b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs @@ -1,7 +1,7 @@ use if_chain::if_chain; use rustc::hir::*; use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use crate::utils::{self, paths, span_lint}; @@ -42,17 +42,7 @@ declare_clippy_lint! { "The use of negated comparison operators on partially ordered types may produce confusing code." } -pub struct NoNegCompOpForPartialOrd; - -impl LintPass for NoNegCompOpForPartialOrd { - fn get_lints(&self) -> LintArray { - lint_array!(NEG_CMP_OP_ON_PARTIAL_ORD) - } - - fn name(&self) -> &'static str { - "NoNegCompOpForPartialOrd" - } -} +declare_lint_pass!(NoNegCompOpForPartialOrd => [NEG_CMP_OP_ON_PARTIAL_ORD]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NoNegCompOpForPartialOrd { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { diff --git a/clippy_lints/src/neg_multiply.rs b/clippy_lints/src/neg_multiply.rs index 757a3cb6cd5b..c235661a432b 100644 --- a/clippy_lints/src/neg_multiply.rs +++ b/clippy_lints/src/neg_multiply.rs @@ -1,7 +1,7 @@ use if_chain::if_chain; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use syntax::source_map::{Span, Spanned}; use crate::consts::{self, Constant}; @@ -23,18 +23,7 @@ declare_clippy_lint! { "multiplying integers with -1" } -#[derive(Copy, Clone)] -pub struct NegMultiply; - -impl LintPass for NegMultiply { - fn get_lints(&self) -> LintArray { - lint_array!(NEG_MULTIPLY) - } - - fn name(&self) -> &'static str { - "NegMultiply" - } -} +declare_lint_pass!(NegMultiply => [NEG_MULTIPLY]); #[allow(clippy::match_same_arms)] impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NegMultiply { diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index 3bf0c22c322c..55a4b1588c2b 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -7,7 +7,7 @@ use rustc::hir::def_id::DefId; use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass}; use rustc::ty::{self, Ty}; use rustc::util::nodemap::NodeSet; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_tool_lint, impl_lint_pass}; use rustc_errors::Applicability; use syntax::source_map::Span; @@ -89,15 +89,7 @@ pub struct NewWithoutDefault { impling_types: Option, } -impl LintPass for NewWithoutDefault { - fn get_lints(&self) -> LintArray { - lint_array!(NEW_WITHOUT_DEFAULT) - } - - fn name(&self) -> &'static str { - "NewWithoutDefault" - } -} +impl_lint_pass!(NewWithoutDefault => [NEW_WITHOUT_DEFAULT]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::Item) { diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index 74a9b353ea97..1836e929e180 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -2,7 +2,7 @@ use crate::utils::{has_drop, in_macro, snippet_opt, span_lint, span_lint_and_sug use rustc::hir::def::Def; use rustc::hir::{BinOpKind, BlockCheckMode, Expr, ExprKind, Stmt, StmtKind, UnsafeSource}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; use std::ops::Deref; @@ -93,20 +93,9 @@ fn has_no_effect(cx: &LateContext<'_, '_>, expr: &Expr) -> bool { } } -#[derive(Copy, Clone)] -pub struct Pass; +declare_lint_pass!(NoEffect => [NO_EFFECT, UNNECESSARY_OPERATION]); -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(NO_EFFECT, UNNECESSARY_OPERATION) - } - - fn name(&self) -> &'static str { - "NoEffect" - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NoEffect { fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt) { if let StmtKind::Semi(ref expr) = stmt.node { if has_no_effect(cx, expr) { diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs index 8b7b6b6c42c6..1d947784576a 100644 --- a/clippy_lints/src/non_copy_const.rs +++ b/clippy_lints/src/non_copy_const.rs @@ -9,7 +9,7 @@ use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, Lint, LintArray, LintPass}; use rustc::ty::adjustment::Adjust; use rustc::ty::{Ty, TypeFlags}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; use rustc_typeck::hir_ty_to_ty; use syntax_pos::{Span, DUMMY_SP}; @@ -143,17 +143,7 @@ fn verify_ty_bound<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>, source: S }); } -pub struct NonCopyConst; - -impl LintPass for NonCopyConst { - fn get_lints(&self) -> LintArray { - lint_array!(DECLARE_INTERIOR_MUTABLE_CONST, BORROW_INTERIOR_MUTABLE_CONST) - } - - fn name(&self) -> &'static str { - "NonCopyConst" - } -} +declare_lint_pass!(NonCopyConst => [DECLARE_INTERIOR_MUTABLE_CONST, BORROW_INTERIOR_MUTABLE_CONST]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonCopyConst { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, it: &'tcx Item) { diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index 39d69d0bd51b..b1d180c6ceb3 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -1,6 +1,6 @@ use crate::utils::{span_lint, span_lint_and_then}; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_tool_lint, impl_lint_pass}; use syntax::ast::*; use syntax::attr; use syntax::source_map::Span; @@ -63,19 +63,12 @@ declare_clippy_lint! { "unclear name" } +#[derive(Copy, Clone)] pub struct NonExpressiveNames { pub single_char_binding_names_threshold: u64, } -impl LintPass for NonExpressiveNames { - fn get_lints(&self) -> LintArray { - lint_array!(SIMILAR_NAMES, MANY_SINGLE_CHAR_NAMES, JUST_UNDERSCORES_AND_DIGITS) - } - - fn name(&self) -> &'static str { - "NoneExpressiveNames" - } -} +impl_lint_pass!(NonExpressiveNames => [SIMILAR_NAMES, MANY_SINGLE_CHAR_NAMES, JUST_UNDERSCORES_AND_DIGITS]); struct ExistingName { interned: LocalInternedString, diff --git a/clippy_lints/src/ok_if_let.rs b/clippy_lints/src/ok_if_let.rs index 11c392b581ad..01d41f679dbb 100644 --- a/clippy_lints/src/ok_if_let.rs +++ b/clippy_lints/src/ok_if_let.rs @@ -2,7 +2,7 @@ use crate::utils::{match_type, method_chain_args, paths, snippet, span_help_and_ use if_chain::if_chain; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { /// **What it does:*** Checks for unnecessary `ok()` in if let. @@ -34,20 +34,9 @@ declare_clippy_lint! { "usage of `ok()` in `if let Some(pat)` statements is unnecessary, match on `Ok(pat)` instead" } -#[derive(Copy, Clone)] -pub struct Pass; +declare_lint_pass!(OkIfLet => [IF_LET_SOME_RESULT]); -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(IF_LET_SOME_RESULT) - } - - fn name(&self) -> &'static str { - "OkIfLet" - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OkIfLet { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if_chain! { //begin checking variables if let ExprKind::Match(ref op, ref body, ref source) = expr.node; //test if expr is a match diff --git a/clippy_lints/src/open_options.rs b/clippy_lints/src/open_options.rs index 43c7f3884d3a..062534333c23 100644 --- a/clippy_lints/src/open_options.rs +++ b/clippy_lints/src/open_options.rs @@ -1,7 +1,7 @@ use crate::utils::{match_type, paths, span_lint, walk_ptrs_ty}; use rustc::hir::{Expr, ExprKind}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use syntax::ast::LitKind; use syntax::source_map::{Span, Spanned}; @@ -25,20 +25,9 @@ declare_clippy_lint! { "nonsensical combination of options for opening a file" } -#[derive(Copy, Clone)] -pub struct NonSensical; +declare_lint_pass!(OpenOptions => [NONSENSICAL_OPEN_OPTIONS]); -impl LintPass for NonSensical { - fn get_lints(&self) -> LintArray { - lint_array!(NONSENSICAL_OPEN_OPTIONS) - } - - fn name(&self) -> &'static str { - "OpenOptions" - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSensical { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OpenOptions { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { if let ExprKind::MethodCall(ref path, _, ref arguments) = e.node { let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(&arguments[0])); diff --git a/clippy_lints/src/overflow_check_conditional.rs b/clippy_lints/src/overflow_check_conditional.rs index c041f3a959a0..c598e915a5af 100644 --- a/clippy_lints/src/overflow_check_conditional.rs +++ b/clippy_lints/src/overflow_check_conditional.rs @@ -2,7 +2,7 @@ use crate::utils::{span_lint, SpanlessEq}; use if_chain::if_chain; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { /// **What it does:** Detects classic underflow/overflow checks. @@ -21,18 +21,7 @@ declare_clippy_lint! { "overflow checks inspired by C which are likely to panic" } -#[derive(Copy, Clone)] -pub struct OverflowCheckConditional; - -impl LintPass for OverflowCheckConditional { - fn get_lints(&self) -> LintArray { - lint_array!(OVERFLOW_CHECK_CONDITIONAL) - } - - fn name(&self) -> &'static str { - "OverflowCheckConditional" - } -} +declare_lint_pass!(OverflowCheckConditional => [OVERFLOW_CHECK_CONDITIONAL]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OverflowCheckConditional { // a + b < a, a > a + b, a < a - b, a - b > a diff --git a/clippy_lints/src/panic_unimplemented.rs b/clippy_lints/src/panic_unimplemented.rs index 66624a066751..57ff7536a386 100644 --- a/clippy_lints/src/panic_unimplemented.rs +++ b/clippy_lints/src/panic_unimplemented.rs @@ -1,8 +1,8 @@ -use crate::utils::{is_direct_expn_of, is_expn_of, match_def_path, paths, resolve_node, span_lint}; +use crate::utils::{is_direct_expn_of, is_expn_of, paths, resolve_node, span_lint}; use if_chain::if_chain; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use syntax::ast::LitKind; use syntax::ptr::P; use syntax_pos::Span; @@ -42,19 +42,9 @@ declare_clippy_lint! { "`unimplemented!` should not be present in production code" } -pub struct Pass; +declare_lint_pass!(PanicUnimplemented => [PANIC_PARAMS, UNIMPLEMENTED]); -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(PANIC_PARAMS, UNIMPLEMENTED) - } - - fn name(&self) -> &'static str { - "PanicUnimplemented" - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PanicUnimplemented { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if_chain! { if let ExprKind::Block(ref block, _) = expr.node; @@ -62,7 +52,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if let ExprKind::Call(ref fun, ref params) = ex.node; if let ExprKind::Path(ref qpath) = fun.node; if let Some(fun_def_id) = resolve_node(cx, qpath, fun.hir_id).opt_def_id(); - if match_def_path(cx.tcx, fun_def_id, &paths::BEGIN_PANIC); + if cx.match_def_path(fun_def_id, &paths::BEGIN_PANIC); if params.len() == 2; then { if is_expn_of(expr.span, "unimplemented").is_some() { diff --git a/clippy_lints/src/partialeq_ne_impl.rs b/clippy_lints/src/partialeq_ne_impl.rs index 2f034b9f1aac..6a6725b4d10b 100644 --- a/clippy_lints/src/partialeq_ne_impl.rs +++ b/clippy_lints/src/partialeq_ne_impl.rs @@ -2,7 +2,7 @@ use crate::utils::{is_automatically_derived, span_lint_hir}; use if_chain::if_chain; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { /// **What it does:** Checks for manual re-implementations of `PartialEq::ne`. @@ -28,20 +28,9 @@ declare_clippy_lint! { "re-implementing `PartialEq::ne`" } -#[derive(Clone, Copy)] -pub struct Pass; +declare_lint_pass!(PartialEqNeImpl => [PARTIALEQ_NE_IMPL]); -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(PARTIALEQ_NE_IMPL) - } - - fn name(&self) -> &'static str { - "PartialEqNeImpl" - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PartialEqNeImpl { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { if_chain! { if let ItemKind::Impl(_, _, _, _, Some(ref trait_ref), _, ref impl_items) = item.node; diff --git a/clippy_lints/src/path_buf_push_overwrite.rs b/clippy_lints/src/path_buf_push_overwrite.rs new file mode 100644 index 000000000000..ce9947298fa5 --- /dev/null +++ b/clippy_lints/src/path_buf_push_overwrite.rs @@ -0,0 +1,71 @@ +use crate::utils::{match_type, paths, span_lint_and_sugg, walk_ptrs_ty}; +use if_chain::if_chain; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_lint_pass, declare_tool_lint}; +use rustc_errors::Applicability; +use std::path::{Component, Path}; +use syntax::ast::LitKind; + +declare_clippy_lint! { + /// **What it does:*** Checks for [push](https://doc.rust-lang.org/std/path/struct.PathBuf.html#method.push) + /// calls on `PathBuf` that can cause overwrites. + /// + /// **Why is this bad?** Calling `push` with a root path at the start can overwrite the + /// previous defined path. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// ```rust + /// use std::path::PathBuf; + /// + /// let mut x = PathBuf::from("/foo"); + /// x.push("/bar"); + /// assert_eq!(x, PathBuf::from("/bar")); + /// ``` + /// Could be written: + /// + /// ```rust + /// use std::path::PathBuf; + /// + /// let mut x = PathBuf::from("/foo"); + /// x.push("bar"); + /// assert_eq!(x, PathBuf::from("/foo/bar")); + /// ``` + pub PATH_BUF_PUSH_OVERWRITE, + nursery, + "calling `push` with file system root on `PathBuf` can overwrite it" +} + +declare_lint_pass!(PathBufPushOverwrite => [PATH_BUF_PUSH_OVERWRITE]); + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PathBufPushOverwrite { + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { + if_chain! { + if let ExprKind::MethodCall(ref path, _, ref args) = expr.node; + if path.ident.name == "push"; + if args.len() == 2; + if match_type(cx, walk_ptrs_ty(cx.tables.expr_ty(&args[0])), &paths::PATH_BUF); + if let Some(get_index_arg) = args.get(1); + if let ExprKind::Lit(ref lit) = get_index_arg.node; + if let LitKind::Str(ref path_lit, _) = lit.node; + if let pushed_path = Path::new(&path_lit.as_str()); + if let Some(pushed_path_lit) = pushed_path.to_str(); + if pushed_path.has_root(); + if let Some(root) = pushed_path.components().next(); + if root == Component::RootDir; + then { + span_lint_and_sugg( + cx, + PATH_BUF_PUSH_OVERWRITE, + lit.span, + "Calling `push` with '/' or '\\' (file system root) will overwrite the previous path definition", + "try", + format!("\"{}\"", pushed_path_lit.trim_start_matches(|c| c == '/' || c == '\\')), + Applicability::MachineApplicable, + ); + } + } + } +} diff --git a/clippy_lints/src/precedence.rs b/clippy_lints/src/precedence.rs index 6819ac744744..52c11cacaac0 100644 --- a/clippy_lints/src/precedence.rs +++ b/clippy_lints/src/precedence.rs @@ -1,6 +1,6 @@ use crate::utils::{in_macro, snippet_with_applicability, span_lint_and_sugg}; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; use syntax::ast::*; use syntax::source_map::Spanned; @@ -28,18 +28,7 @@ declare_clippy_lint! { "operations where precedence may be unclear" } -#[derive(Copy, Clone)] -pub struct Precedence; - -impl LintPass for Precedence { - fn get_lints(&self) -> LintArray { - lint_array!(PRECEDENCE) - } - - fn name(&self) -> &'static str { - "Precedence" - } -} +declare_lint_pass!(Precedence => [PRECEDENCE]); impl EarlyLintPass for Precedence { fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 331f4216d26f..af69d62ddb73 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -7,7 +7,7 @@ use rustc::hir::QPath; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::ty; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; use std::borrow::Cow; use syntax::source_map::Span; @@ -94,20 +94,9 @@ declare_clippy_lint! { "fns that create mutable refs from immutable ref args" } -#[derive(Copy, Clone)] -pub struct PointerPass; +declare_lint_pass!(Ptr => [PTR_ARG, CMP_NULL, MUT_FROM_REF]); -impl LintPass for PointerPass { - fn get_lints(&self) -> LintArray { - lint_array!(PTR_ARG, CMP_NULL, MUT_FROM_REF) - } - - fn name(&self) -> &'static str { - "Ptr" - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PointerPass { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Ptr { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { if let ItemKind::Fn(ref decl, _, _, body_id) = item.node { check_fn(cx, decl, item.hir_id, Some(body_id)); diff --git a/clippy_lints/src/ptr_offset_with_cast.rs b/clippy_lints/src/ptr_offset_with_cast.rs index 21c7e7213382..2d3c3298f584 100644 --- a/clippy_lints/src/ptr_offset_with_cast.rs +++ b/clippy_lints/src/ptr_offset_with_cast.rs @@ -1,5 +1,7 @@ use crate::utils; -use rustc::{declare_tool_lint, hir, lint, lint_array}; +use rustc::hir::{Expr, ExprKind}; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; use std::fmt; @@ -39,21 +41,10 @@ declare_clippy_lint! { "unneeded pointer offset cast" } -#[derive(Copy, Clone, Debug)] -pub struct Pass; +declare_lint_pass!(PtrOffsetWithCast => [PTR_OFFSET_WITH_CAST]); -impl lint::LintPass for Pass { - fn get_lints(&self) -> lint::LintArray { - lint_array!(PTR_OFFSET_WITH_CAST) - } - - fn name(&self) -> &'static str { - "PtrOffsetWithCast" - } -} - -impl<'a, 'tcx> lint::LateLintPass<'a, 'tcx> for Pass { - fn check_expr(&mut self, cx: &lint::LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PtrOffsetWithCast { + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { // Check if the expressions is a ptr.offset or ptr.wrapping_offset method call let (receiver_expr, arg_expr, method) = match expr_as_ptr_offset_call(cx, expr) { Some(call_arg) => call_arg, @@ -84,11 +75,8 @@ impl<'a, 'tcx> lint::LateLintPass<'a, 'tcx> for Pass { } // If the given expression is a cast from a usize, return the lhs of the cast -fn expr_as_cast_from_usize<'a, 'tcx>( - cx: &lint::LateContext<'a, 'tcx>, - expr: &'tcx hir::Expr, -) -> Option<&'tcx hir::Expr> { - if let hir::ExprKind::Cast(ref cast_lhs_expr, _) = expr.node { +fn expr_as_cast_from_usize<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) -> Option<&'tcx Expr> { + if let ExprKind::Cast(ref cast_lhs_expr, _) = expr.node { if is_expr_ty_usize(cx, &cast_lhs_expr) { return Some(cast_lhs_expr); } @@ -99,10 +87,10 @@ fn expr_as_cast_from_usize<'a, 'tcx>( // If the given expression is a ptr::offset or ptr::wrapping_offset method call, return the // receiver, the arg of the method call, and the method. fn expr_as_ptr_offset_call<'a, 'tcx>( - cx: &lint::LateContext<'a, 'tcx>, - expr: &'tcx hir::Expr, -) -> Option<(&'tcx hir::Expr, &'tcx hir::Expr, Method)> { - if let hir::ExprKind::MethodCall(ref path_segment, _, ref args) = expr.node { + cx: &LateContext<'a, 'tcx>, + expr: &'tcx Expr, +) -> Option<(&'tcx Expr, &'tcx Expr, Method)> { + if let ExprKind::MethodCall(ref path_segment, _, ref args) = expr.node { if is_expr_ty_raw_ptr(cx, &args[0]) { if path_segment.ident.name == "offset" { return Some((&args[0], &args[1], Method::Offset)); @@ -116,20 +104,20 @@ fn expr_as_ptr_offset_call<'a, 'tcx>( } // Is the type of the expression a usize? -fn is_expr_ty_usize<'a, 'tcx>(cx: &lint::LateContext<'a, 'tcx>, expr: &hir::Expr) -> bool { +fn is_expr_ty_usize<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr) -> bool { cx.tables.expr_ty(expr) == cx.tcx.types.usize } // Is the type of the expression a raw pointer? -fn is_expr_ty_raw_ptr<'a, 'tcx>(cx: &lint::LateContext<'a, 'tcx>, expr: &hir::Expr) -> bool { +fn is_expr_ty_raw_ptr<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr) -> bool { cx.tables.expr_ty(expr).is_unsafe_ptr() } fn build_suggestion<'a, 'tcx>( - cx: &lint::LateContext<'a, 'tcx>, + cx: &LateContext<'a, 'tcx>, method: Method, - receiver_expr: &hir::Expr, - cast_lhs_expr: &hir::Expr, + receiver_expr: &Expr, + cast_lhs_expr: &Expr, ) -> Option { let receiver = utils::snippet_opt(cx, receiver_expr.span)?; let cast_lhs = utils::snippet_opt(cx, cast_lhs_expr.span)?; diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index 5c64cd1c15c7..c5388905032c 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -2,13 +2,13 @@ use if_chain::if_chain; use rustc::hir::def::Def; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; use syntax::ptr::P; use crate::utils::paths::*; use crate::utils::sugg::Sugg; -use crate::utils::{match_def_path, match_type, span_lint_and_then, SpanlessEq}; +use crate::utils::{match_type, span_lint_and_then, SpanlessEq}; declare_clippy_lint! { /// **What it does:** Checks for expressions that could be replaced by the question mark operator. @@ -34,20 +34,9 @@ declare_clippy_lint! { "checks for expressions that could be replaced by the question mark operator" } -#[derive(Copy, Clone)] -pub struct Pass; +declare_lint_pass!(QuestionMark => [QUESTION_MARK]); -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(QUESTION_MARK) - } - - fn name(&self) -> &'static str { - "QuestionMark" - } -} - -impl Pass { +impl QuestionMark { /// Checks if the given expression on the given context matches the following structure: /// /// ```ignore @@ -129,7 +118,7 @@ impl Pass { ExprKind::Ret(Some(ref expr)) => Self::expression_returns_none(cx, expr), ExprKind::Path(ref qp) => { if let Def::Ctor(def_id, def::CtorOf::Variant, _) = cx.tables.qpath_def(qp, expression.hir_id) { - return match_def_path(cx.tcx, def_id, &OPTION_NONE); + return cx.match_def_path(def_id, &OPTION_NONE); } false @@ -165,7 +154,7 @@ impl Pass { } } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for QuestionMark { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { Self::check_is_none_and_early_return_none(cx, expr); } diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index 84c9509844fc..a18ee4c2b896 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -1,7 +1,7 @@ use if_chain::if_chain; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; use syntax::ast::RangeLimits; use syntax::source_map::Spanned; @@ -86,25 +86,14 @@ declare_clippy_lint! { "`x..=(y-1)` reads better as `x..y`" } -#[derive(Copy, Clone)] -pub struct Pass; +declare_lint_pass!(Ranges => [ + ITERATOR_STEP_BY_ZERO, + RANGE_ZIP_WITH_LEN, + RANGE_PLUS_ONE, + RANGE_MINUS_ONE +]); -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!( - ITERATOR_STEP_BY_ZERO, - RANGE_ZIP_WITH_LEN, - RANGE_PLUS_ONE, - RANGE_MINUS_ONE - ) - } - - fn name(&self) -> &'static str { - "Ranges" - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Ranges { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if let ExprKind::MethodCall(ref path, _, ref args) = expr.node { let name = path.ident.as_str(); diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index c764e0ceb837..92628cfb4a48 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -1,5 +1,5 @@ use crate::utils::{ - has_drop, in_macro, is_copy, match_def_path, match_type, paths, snippet_opt, span_lint_hir, span_lint_hir_and_then, + has_drop, in_macro, is_copy, match_type, paths, snippet_opt, span_lint_hir, span_lint_hir_and_then, walk_ptrs_ty_depth, }; use if_chain::if_chain; @@ -13,7 +13,7 @@ use rustc::mir::{ TerminatorKind, }; use rustc::ty::{self, Ty}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; use std::convert::TryFrom; use syntax::source_map::{BytePos, Span}; @@ -64,17 +64,7 @@ declare_clippy_lint! { "`clone()` of an owned value that is going to be dropped immediately" } -pub struct RedundantClone; - -impl LintPass for RedundantClone { - fn get_lints(&self) -> LintArray { - lint_array!(REDUNDANT_CLONE) - } - - fn name(&self) -> &'static str { - "RedundantClone" - } -} +declare_lint_pass!(RedundantClone => [REDUNDANT_CLONE]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone { #[allow(clippy::too_many_lines)] @@ -104,14 +94,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone { let (fn_def_id, arg, arg_ty, _) = unwrap_or_continue!(is_call_with_ref_arg(cx, mir, &terminator.kind)); - let from_borrow = match_def_path(cx.tcx, fn_def_id, &paths::CLONE_TRAIT_METHOD) - || match_def_path(cx.tcx, fn_def_id, &paths::TO_OWNED_METHOD) - || (match_def_path(cx.tcx, fn_def_id, &paths::TO_STRING_METHOD) - && match_type(cx, arg_ty, &paths::STRING)); + let from_borrow = cx.match_def_path(fn_def_id, &paths::CLONE_TRAIT_METHOD) + || cx.match_def_path(fn_def_id, &paths::TO_OWNED_METHOD) + || (cx.match_def_path(fn_def_id, &paths::TO_STRING_METHOD) && match_type(cx, arg_ty, &paths::STRING)); let from_deref = !from_borrow - && (match_def_path(cx.tcx, fn_def_id, &paths::PATH_TO_PATH_BUF) - || match_def_path(cx.tcx, fn_def_id, &paths::OS_STR_TO_OS_STRING)); + && (cx.match_def_path(fn_def_id, &paths::PATH_TO_PATH_BUF) + || cx.match_def_path(fn_def_id, &paths::OS_STR_TO_OS_STRING)); if !from_borrow && !from_deref { continue; @@ -144,7 +133,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone { if let Some((pred_fn_def_id, pred_arg, pred_arg_ty, Some(res))) = is_call_with_ref_arg(cx, mir, &pred_terminator.kind); if *res == mir::Place::Base(mir::PlaceBase::Local(cloned)); - if match_def_path(cx.tcx, pred_fn_def_id, &paths::DEREF_TRAIT_METHOD); + if cx.match_def_path(pred_fn_def_id, &paths::DEREF_TRAIT_METHOD); if match_type(cx, pred_arg_ty, &paths::PATH_BUF) || match_type(cx, pred_arg_ty, &paths::OS_STRING); then { diff --git a/clippy_lints/src/redundant_field_names.rs b/clippy_lints/src/redundant_field_names.rs index 7e53035d9dce..389f72057890 100644 --- a/clippy_lints/src/redundant_field_names.rs +++ b/clippy_lints/src/redundant_field_names.rs @@ -1,6 +1,6 @@ use crate::utils::span_lint_and_sugg; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; use syntax::ast::*; @@ -32,17 +32,7 @@ declare_clippy_lint! { "checks for fields in struct literals where shorthands could be used" } -pub struct RedundantFieldNames; - -impl LintPass for RedundantFieldNames { - fn get_lints(&self) -> LintArray { - lint_array!(REDUNDANT_FIELD_NAMES) - } - - fn name(&self) -> &'static str { - "RedundantFieldNames" - } -} +declare_lint_pass!(RedundantFieldNames => [REDUNDANT_FIELD_NAMES]); impl EarlyLintPass for RedundantFieldNames { fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { diff --git a/clippy_lints/src/redundant_pattern_matching.rs b/clippy_lints/src/redundant_pattern_matching.rs index ebc5e240a954..fe1a29b98833 100644 --- a/clippy_lints/src/redundant_pattern_matching.rs +++ b/clippy_lints/src/redundant_pattern_matching.rs @@ -1,7 +1,7 @@ use crate::utils::{match_qpath, paths, snippet, span_lint_and_then}; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; use syntax::ast::LitKind; use syntax::ptr::P; @@ -42,20 +42,9 @@ declare_clippy_lint! { "use the proper utility function avoiding an `if let`" } -#[derive(Copy, Clone)] -pub struct Pass; +declare_lint_pass!(RedundantPatternMatching => [REDUNDANT_PATTERN_MATCHING]); -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(REDUNDANT_PATTERN_MATCHING) - } - - fn name(&self) -> &'static str { - "RedundantPatternMatching" - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantPatternMatching { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if let ExprKind::Match(ref op, ref arms, ref match_source) = expr.node { match match_source { diff --git a/clippy_lints/src/reference.rs b/clippy_lints/src/reference.rs index d5447027acba..2ee00a2f1034 100644 --- a/clippy_lints/src/reference.rs +++ b/clippy_lints/src/reference.rs @@ -1,7 +1,7 @@ use crate::utils::{snippet_with_applicability, span_lint_and_sugg}; use if_chain::if_chain; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; use syntax::ast::{Expr, ExprKind, UnOp}; @@ -24,17 +24,7 @@ declare_clippy_lint! { "use of `*&` or `*&mut` in an expression" } -pub struct Pass; - -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(DEREF_ADDROF) - } - - fn name(&self) -> &'static str { - "DerefAddrOf" - } -} +declare_lint_pass!(DerefAddrOf => [DEREF_ADDROF]); fn without_parens(mut e: &Expr) -> &Expr { while let ExprKind::Paren(ref child_e) = e.node { @@ -43,7 +33,7 @@ fn without_parens(mut e: &Expr) -> &Expr { e } -impl EarlyLintPass for Pass { +impl EarlyLintPass for DerefAddrOf { fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &Expr) { if_chain! { if let ExprKind::Unary(UnOp::Deref, ref deref_target) = e.node; @@ -82,19 +72,9 @@ declare_clippy_lint! { "Use of reference in auto dereference expression." } -pub struct DerefPass; - -impl LintPass for DerefPass { - fn get_lints(&self) -> LintArray { - lint_array!(REF_IN_DEREF) - } - - fn name(&self) -> &'static str { - "RefInDeref" - } -} +declare_lint_pass!(RefInDeref => [REF_IN_DEREF]); -impl EarlyLintPass for DerefPass { +impl EarlyLintPass for RefInDeref { fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &Expr) { if_chain! { if let ExprKind::Field(ref object, _) = e.node; diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index 094b6124076c..2c912741f8ca 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -1,10 +1,10 @@ use crate::consts::{constant, Constant}; -use crate::utils::{is_expn_of, match_def_path, match_type, paths, span_help_and_lint, span_lint}; +use crate::utils::{is_expn_of, match_type, paths, span_help_and_lint, span_lint}; use if_chain::if_chain; use regex_syntax; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_tool_lint, impl_lint_pass}; use rustc_data_structures::fx::FxHashSet; use std::convert::TryFrom; use syntax::ast::{LitKind, StrStyle}; @@ -67,22 +67,14 @@ declare_clippy_lint! { } #[derive(Clone, Default)] -pub struct Pass { +pub struct Regex { spans: FxHashSet, last: Option, } -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(INVALID_REGEX, REGEX_MACRO, TRIVIAL_REGEX) - } - - fn name(&self) -> &'static str { - "Regex" - } -} +impl_lint_pass!(Regex => [INVALID_REGEX, REGEX_MACRO, TRIVIAL_REGEX]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Regex { fn check_crate(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx Crate) { self.spans.clear(); } @@ -120,15 +112,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if args.len() == 1; if let Some(def_id) = cx.tables.qpath_def(qpath, fun.hir_id).opt_def_id(); then { - if match_def_path(cx.tcx, def_id, &paths::REGEX_NEW) || - match_def_path(cx.tcx, def_id, &paths::REGEX_BUILDER_NEW) { + if cx.match_def_path(def_id, &paths::REGEX_NEW) || + cx.match_def_path(def_id, &paths::REGEX_BUILDER_NEW) { check_regex(cx, &args[0], true); - } else if match_def_path(cx.tcx, def_id, &paths::REGEX_BYTES_NEW) || - match_def_path(cx.tcx, def_id, &paths::REGEX_BYTES_BUILDER_NEW) { + } else if cx.match_def_path(def_id, &paths::REGEX_BYTES_NEW) || + cx.match_def_path(def_id, &paths::REGEX_BYTES_BUILDER_NEW) { check_regex(cx, &args[0], false); - } else if match_def_path(cx.tcx, def_id, &paths::REGEX_SET_NEW) { + } else if cx.match_def_path(def_id, &paths::REGEX_SET_NEW) { check_set(cx, &args[0], true); - } else if match_def_path(cx.tcx, def_id, &paths::REGEX_BYTES_SET_NEW) { + } else if cx.match_def_path(def_id, &paths::REGEX_BYTES_SET_NEW) { check_set(cx, &args[0], false); } } diff --git a/clippy_lints/src/replace_consts.rs b/clippy_lints/src/replace_consts.rs index 10e339eeb023..4dc5cea450d1 100644 --- a/clippy_lints/src/replace_consts.rs +++ b/clippy_lints/src/replace_consts.rs @@ -1,9 +1,9 @@ -use crate::utils::{match_def_path, span_lint_and_sugg}; +use crate::utils::span_lint_and_sugg; use if_chain::if_chain; use rustc::hir; use rustc::hir::def::Def; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; declare_clippy_lint! { @@ -29,17 +29,7 @@ declare_clippy_lint! { "Lint usages of standard library `const`s that could be replaced by `const fn`s" } -pub struct ReplaceConsts; - -impl LintPass for ReplaceConsts { - fn get_lints(&self) -> LintArray { - lint_array!(REPLACE_CONSTS) - } - - fn name(&self) -> &'static str { - "ReplaceConsts" - } -} +declare_lint_pass!(ReplaceConsts => [REPLACE_CONSTS]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ReplaceConsts { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) { @@ -48,7 +38,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ReplaceConsts { if let Def::Const(def_id) = cx.tables.qpath_def(qp, expr.hir_id); then { for &(const_path, repl_snip) in REPLACEMENTS { - if match_def_path(cx.tcx, def_id, const_path) { + if cx.match_def_path(def_id, const_path) { span_lint_and_sugg( cx, REPLACE_CONSTS, diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 3995d9f2819c..ba871c464ead 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -1,6 +1,6 @@ use if_chain::if_chain; use rustc::lint::{in_external_macro, EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; use syntax::ast; use syntax::source_map::Span; @@ -83,10 +83,9 @@ declare_clippy_lint! { "needless unit expression" } -#[derive(Copy, Clone)] -pub struct ReturnPass; +declare_lint_pass!(Return => [NEEDLESS_RETURN, LET_AND_RETURN, UNUSED_UNIT]); -impl ReturnPass { +impl Return { // Check the final stmt or expr in a block for unnecessary return. fn check_block_return(&mut self, cx: &EarlyContext<'_>, block: &ast::Block) { if let Some(stmt) = block.stmts.last() { @@ -177,17 +176,7 @@ impl ReturnPass { } } -impl LintPass for ReturnPass { - fn get_lints(&self) -> LintArray { - lint_array!(NEEDLESS_RETURN, LET_AND_RETURN, UNUSED_UNIT) - } - - fn name(&self) -> &'static str { - "Return" - } -} - -impl EarlyLintPass for ReturnPass { +impl EarlyLintPass for Return { fn check_fn(&mut self, cx: &EarlyContext<'_>, kind: FnKind<'_>, decl: &ast::FnDecl, span: Span, _: ast::NodeId) { match kind { FnKind::ItemFn(.., block) | FnKind::Method(.., block) => self.check_block_return(cx, block), diff --git a/clippy_lints/src/serde_api.rs b/clippy_lints/src/serde_api.rs index e9479af54190..f3d4ff35d487 100644 --- a/clippy_lints/src/serde_api.rs +++ b/clippy_lints/src/serde_api.rs @@ -1,7 +1,7 @@ use crate::utils::{get_trait_def_id, paths, span_lint}; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { /// **What it does:** Checks for mis-uses of the serde API. @@ -18,20 +18,9 @@ declare_clippy_lint! { "various things that will negatively affect your serde experience" } -#[derive(Copy, Clone)] -pub struct Serde; +declare_lint_pass!(SerdeAPI => [SERDE_API_MISUSE]); -impl LintPass for Serde { - fn get_lints(&self) -> LintArray { - lint_array!(SERDE_API_MISUSE) - } - - fn name(&self) -> &'static str { - "SerdeAPI" - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Serde { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for SerdeAPI { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { if let ItemKind::Impl(_, _, _, _, Some(ref trait_ref), _, ref items) = item.node { let did = trait_ref.path.def.def_id(); diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index 99580affef67..e43b591a9cdc 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -4,7 +4,7 @@ use rustc::hir::intravisit::FnKind; use rustc::hir::*; use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass}; use rustc::ty; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use syntax::source_map::Span; declare_clippy_lint! { @@ -75,20 +75,9 @@ declare_clippy_lint! { "rebinding a name without even using the original value" } -#[derive(Copy, Clone)] -pub struct Pass; +declare_lint_pass!(Shadow => [SHADOW_SAME, SHADOW_REUSE, SHADOW_UNRELATED]); -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(SHADOW_SAME, SHADOW_REUSE, SHADOW_UNRELATED) - } - - fn name(&self) -> &'static str { - "Shadow" - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Shadow { fn check_fn( &mut self, cx: &LateContext<'a, 'tcx>, diff --git a/clippy_lints/src/slow_vector_initialization.rs b/clippy_lints/src/slow_vector_initialization.rs index 888405983fd5..0bc992b3191b 100644 --- a/clippy_lints/src/slow_vector_initialization.rs +++ b/clippy_lints/src/slow_vector_initialization.rs @@ -4,7 +4,7 @@ use if_chain::if_chain; use rustc::hir::intravisit::{walk_block, walk_expr, walk_stmt, NestedVisitorMap, Visitor}; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, Lint, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; use syntax::ast::LitKind; use syntax_pos::symbol::Symbol; @@ -30,18 +30,7 @@ declare_clippy_lint! { "slow vector initialization" } -#[derive(Copy, Clone, Default)] -pub struct Pass; - -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(SLOW_VECTOR_INITIALIZATION,) - } - - fn name(&self) -> &'static str { - "SlowVectorInit" - } -} +declare_lint_pass!(SlowVectorInit => [SLOW_VECTOR_INITIALIZATION]); /// `VecAllocation` contains data regarding a vector allocated with `with_capacity` and then /// assigned to a variable. For example, `let mut vec = Vec::with_capacity(0)` or @@ -67,7 +56,7 @@ enum InitializationType<'tcx> { Resize(&'tcx Expr), } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for SlowVectorInit { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { // Matches initialization on reassignements. For example: `vec = Vec::with_capacity(100)` if_chain! { @@ -113,7 +102,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } } -impl Pass { +impl SlowVectorInit { /// Checks if the given expression is `Vec::with_capacity(..)`. It will return the expression /// of the first argument of `with_capacity` call if it matches or `None` if it does not. fn is_vec_with_capacity(expr: &Expr) -> Option<&Expr> { diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index cd23722bef4f..f1f006206ffc 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -1,6 +1,6 @@ use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; use syntax::source_map::Spanned; @@ -73,18 +73,7 @@ declare_clippy_lint! { "calling `as_bytes` on a string literal instead of using a byte string literal" } -#[derive(Copy, Clone)] -pub struct StringAdd; - -impl LintPass for StringAdd { - fn get_lints(&self) -> LintArray { - lint_array!(STRING_ADD, STRING_ADD_ASSIGN) - } - - fn name(&self) -> &'static str { - "StringAdd" - } -} +declare_lint_pass!(StringAdd => [STRING_ADD, STRING_ADD_ASSIGN]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringAdd { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { @@ -149,18 +138,7 @@ fn is_add(cx: &LateContext<'_, '_>, src: &Expr, target: &Expr) -> bool { } } -#[derive(Copy, Clone)] -pub struct StringLitAsBytes; - -impl LintPass for StringLitAsBytes { - fn get_lints(&self) -> LintArray { - lint_array!(STRING_LIT_AS_BYTES) - } - - fn name(&self) -> &'static str { - "StringLiteralAsBytes" - } -} +declare_lint_pass!(StringLitAsBytes => [STRING_LIT_AS_BYTES]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringLitAsBytes { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { diff --git a/clippy_lints/src/suspicious_trait_impl.rs b/clippy_lints/src/suspicious_trait_impl.rs index 76ca1dc28482..f7de396c3897 100644 --- a/clippy_lints/src/suspicious_trait_impl.rs +++ b/clippy_lints/src/suspicious_trait_impl.rs @@ -3,7 +3,7 @@ use if_chain::if_chain; use rustc::hir; use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { /// **What it does:** Lints for suspicious operations in impls of arithmetic operators, e.g. @@ -49,18 +49,7 @@ declare_clippy_lint! { "suspicious use of operators in impl of OpAssign trait" } -#[derive(Copy, Clone)] -pub struct SuspiciousImpl; - -impl LintPass for SuspiciousImpl { - fn get_lints(&self) -> LintArray { - lint_array![SUSPICIOUS_ARITHMETIC_IMPL, SUSPICIOUS_OP_ASSIGN_IMPL] - } - - fn name(&self) -> &'static str { - "SuspiciousImpl" - } -} +declare_lint_pass!(SuspiciousImpl => [SUSPICIOUS_ARITHMETIC_IMPL, SUSPICIOUS_OP_ASSIGN_IMPL]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for SuspiciousImpl { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) { diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index 32a67f394399..fc5b2150d52c 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -7,7 +7,7 @@ use matches::matches; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::ty; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; declare_clippy_lint! { @@ -52,18 +52,7 @@ declare_clippy_lint! { "`foo = bar; bar = foo` sequence" } -#[derive(Copy, Clone)] -pub struct Swap; - -impl LintPass for Swap { - fn get_lints(&self) -> LintArray { - lint_array![MANUAL_SWAP, ALMOST_SWAPPED] - } - - fn name(&self) -> &'static str { - "Swap" - } -} +declare_lint_pass!(Swap => [MANUAL_SWAP, ALMOST_SWAPPED]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Swap { fn check_block(&mut self, cx: &LateContext<'a, 'tcx>, block: &'tcx Block) { diff --git a/clippy_lints/src/temporary_assignment.rs b/clippy_lints/src/temporary_assignment.rs index a6126f372828..e03c6689a106 100644 --- a/clippy_lints/src/temporary_assignment.rs +++ b/clippy_lints/src/temporary_assignment.rs @@ -3,7 +3,7 @@ use crate::utils::span_lint; use rustc::hir::def::Def; use rustc::hir::{Expr, ExprKind}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { /// **What it does:** Checks for construction of a structure or tuple just to @@ -37,20 +37,9 @@ fn is_temporary(cx: &LateContext<'_, '_>, expr: &Expr) -> bool { } } -#[derive(Copy, Clone)] -pub struct Pass; +declare_lint_pass!(TemporaryAssignment => [TEMPORARY_ASSIGNMENT]); -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(TEMPORARY_ASSIGNMENT) - } - - fn name(&self) -> &'static str { - "TemporaryAssignment" - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TemporaryAssignment { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if let ExprKind::Assign(target, _) = &expr.node { let mut base = target; diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index e4eb1bb0b740..d2d3d3cedb71 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -1,9 +1,9 @@ -use crate::utils::{last_path_segment, match_def_path, paths, snippet, span_lint, span_lint_and_then, sugg}; +use crate::utils::{last_path_segment, paths, snippet, span_lint, span_lint_and_then, sugg}; use if_chain::if_chain; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::ty::{self, Ty}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; use std::borrow::Cow; use syntax::ast; @@ -203,27 +203,17 @@ declare_clippy_lint! { "transmutes from a pointer to a pointer / a reference to a reference" } -pub struct Transmute; - -impl LintPass for Transmute { - fn get_lints(&self) -> LintArray { - lint_array!( - CROSSPOINTER_TRANSMUTE, - TRANSMUTE_PTR_TO_REF, - TRANSMUTE_PTR_TO_PTR, - USELESS_TRANSMUTE, - WRONG_TRANSMUTE, - TRANSMUTE_INT_TO_CHAR, - TRANSMUTE_BYTES_TO_STR, - TRANSMUTE_INT_TO_BOOL, - TRANSMUTE_INT_TO_FLOAT, - ) - } - - fn name(&self) -> &'static str { - "Transmute" - } -} +declare_lint_pass!(Transmute => [ + CROSSPOINTER_TRANSMUTE, + TRANSMUTE_PTR_TO_REF, + TRANSMUTE_PTR_TO_PTR, + USELESS_TRANSMUTE, + WRONG_TRANSMUTE, + TRANSMUTE_INT_TO_CHAR, + TRANSMUTE_BYTES_TO_STR, + TRANSMUTE_INT_TO_BOOL, + TRANSMUTE_INT_TO_FLOAT, +]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { #[allow(clippy::similar_names, clippy::too_many_lines)] @@ -231,7 +221,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { if let ExprKind::Call(ref path_expr, ref args) = e.node { if let ExprKind::Path(ref qpath) = path_expr.node { if let Some(def_id) = cx.tables.qpath_def(qpath, path_expr.hir_id).opt_def_id() { - if match_def_path(cx.tcx, def_id, &paths::TRANSMUTE) { + if cx.match_def_path(def_id, &paths::TRANSMUTE) { let from_ty = cx.tables.expr_ty(&args[0]); let to_ty = cx.tables.expr_ty(e); diff --git a/clippy_lints/src/transmuting_null.rs b/clippy_lints/src/transmuting_null.rs index 445abc4832aa..a5bb05dc6418 100644 --- a/clippy_lints/src/transmuting_null.rs +++ b/clippy_lints/src/transmuting_null.rs @@ -3,7 +3,7 @@ use crate::utils::{match_qpath, span_lint}; use if_chain::if_chain; use rustc::hir::{Expr, ExprKind}; use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use syntax::ast::LitKind; declare_clippy_lint! { @@ -24,22 +24,11 @@ declare_clippy_lint! { "transmutes from a null pointer to a reference, which is undefined behavior" } -#[derive(Copy, Clone)] -pub struct Pass; - -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(TRANSMUTING_NULL,) - } - - fn name(&self) -> &'static str { - "TransmutingNull" - } -} +declare_lint_pass!(TransmutingNull => [TRANSMUTING_NULL]); const LINT_MSG: &str = "transmuting a known null pointer into a reference."; -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TransmutingNull { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if in_external_macro(cx.sess(), expr.span) { return; diff --git a/clippy_lints/src/trivially_copy_pass_by_ref.rs b/clippy_lints/src/trivially_copy_pass_by_ref.rs index e0f19a146541..36dba74615a4 100644 --- a/clippy_lints/src/trivially_copy_pass_by_ref.rs +++ b/clippy_lints/src/trivially_copy_pass_by_ref.rs @@ -9,7 +9,7 @@ use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::session::config::Config as SessionConfig; use rustc::ty::{self, FnSig}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_tool_lint, impl_lint_pass}; use rustc_errors::Applicability; use rustc_target::abi::LayoutOf; use rustc_target::spec::abi::Abi; @@ -137,15 +137,7 @@ impl<'a, 'tcx> TriviallyCopyPassByRef { } } -impl LintPass for TriviallyCopyPassByRef { - fn get_lints(&self) -> LintArray { - lint_array![TRIVIALLY_COPY_PASS_BY_REF] - } - - fn name(&self) -> &'static str { - "TrivallyCopyPassByRef" - } -} +impl_lint_pass!(TriviallyCopyPassByRef => [TRIVIALLY_COPY_PASS_BY_REF]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TriviallyCopyPassByRef { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 95609d3f3029..30c7059a4b62 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -1,4 +1,4 @@ -#![allow(clippy::default_hash_types)] +#![allow(default_hash_types)] use std::borrow::Cow; use std::cmp::Ordering; @@ -10,9 +10,8 @@ use rustc::hir::intravisit::{walk_body, walk_expr, walk_ty, FnKind, NestedVisito use rustc::hir::*; use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass}; use rustc::ty::layout::LayoutOf; -use rustc::ty::print::Printer; use rustc::ty::{self, InferTy, Ty, TyCtxt, TypeckTables}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint, impl_lint_pass}; use rustc_errors::Applicability; use rustc_target::spec::abi::Abi; use rustc_typeck::hir_ty_to_ty; @@ -24,13 +23,10 @@ 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, AbsolutePathPrinter, + 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, }; -/// Handles all the linting of funky types -pub struct TypePass; - declare_clippy_lint! { /// **What it does:** Checks for use of `Box>` anywhere in the code. /// @@ -166,17 +162,9 @@ declare_clippy_lint! { "a borrow of a boxed type" } -impl LintPass for TypePass { - fn get_lints(&self) -> LintArray { - lint_array!(BOX_VEC, VEC_BOX, OPTION_OPTION, LINKEDLIST, BORROWED_BOX) - } +declare_lint_pass!(Types => [BOX_VEC, VEC_BOX, OPTION_OPTION, LINKEDLIST, BORROWED_BOX]); - fn name(&self) -> &'static str { - "Types" - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypePass { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Types { fn check_fn(&mut self, cx: &LateContext<'_, '_>, _: FnKind<'_>, decl: &FnDecl, _: &Body, _: Span, id: HirId) { // 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)) { @@ -229,7 +217,7 @@ fn match_type_parameter(cx: &LateContext<'_, '_>, qpath: &QPath, path: &[&str]) }); if let TyKind::Path(ref qpath) = ty.node; if let Some(did) = cx.tables.qpath_def(qpath, ty.hir_id).opt_def_id(); - if match_def_path(cx.tcx, did, path); + if cx.match_def_path(did, path); then { return true; } @@ -263,7 +251,7 @@ fn check_ty(cx: &LateContext<'_, '_>, hir_ty: &hir::Ty, is_local: bool) { ); return; // don't recurse into the type } - } else if match_def_path(cx.tcx, def_id, &paths::VEC) { + } else if cx.match_def_path(def_id, &paths::VEC) { if_chain! { // Get the _ part of Vec<_> if let Some(ref last) = last_path_segment(qpath).args; @@ -298,7 +286,7 @@ fn check_ty(cx: &LateContext<'_, '_>, hir_ty: &hir::Ty, is_local: bool) { } } } - } else if match_def_path(cx.tcx, def_id, &paths::OPTION) { + } else if cx.match_def_path(def_id, &paths::OPTION) { if match_type_parameter(cx, qpath, &paths::OPTION) { span_lint( cx, @@ -309,7 +297,7 @@ fn check_ty(cx: &LateContext<'_, '_>, hir_ty: &hir::Ty, is_local: bool) { ); return; // don't recurse into the type } - } else if match_def_path(cx.tcx, def_id, &paths::LINKED_LIST) { + } else if cx.match_def_path(def_id, &paths::LINKED_LIST) { span_help_and_lint( cx, LINKEDLIST, @@ -447,8 +435,6 @@ fn is_any_trait(t: &hir::Ty) -> bool { false } -pub struct LetPass; - declare_clippy_lint! { /// **What it does:** Checks for binding a unit value. /// @@ -468,17 +454,9 @@ declare_clippy_lint! { "creating a let binding to a value of unit type, which usually can't be used afterwards" } -impl LintPass for LetPass { - fn get_lints(&self) -> LintArray { - lint_array!(LET_UNIT_VALUE) - } - - fn name(&self) -> &'static str { - "LetUnitValue" - } -} +declare_lint_pass!(LetUnitValue => [LET_UNIT_VALUE]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetPass { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetUnitValue { fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt) { if let StmtKind::Local(ref local) = stmt.node { if is_unit(cx.tables.pat_ty(&local.pat)) { @@ -540,17 +518,7 @@ declare_clippy_lint! { "comparing unit values" } -pub struct UnitCmp; - -impl LintPass for UnitCmp { - fn get_lints(&self) -> LintArray { - lint_array!(UNIT_CMP) - } - - fn name(&self) -> &'static str { - "UnicCmp" - } -} +declare_lint_pass!(UnitCmp => [UNIT_CMP]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnitCmp { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { @@ -599,17 +567,7 @@ declare_clippy_lint! { "passing unit to a function" } -pub struct UnitArg; - -impl LintPass for UnitArg { - fn get_lints(&self) -> LintArray { - lint_array!(UNIT_ARG) - } - - fn name(&self) -> &'static str { - "UnitArg" - } -} +declare_lint_pass!(UnitArg => [UNIT_ARG]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnitArg { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { @@ -684,8 +642,6 @@ fn is_unit_literal(expr: &Expr) -> bool { } } -pub struct CastPass; - declare_clippy_lint! { /// **What it does:** Checks for casts from any numerical to a float type where /// the receiving type cannot store all values from the original type without @@ -1114,31 +1070,23 @@ fn check_lossless(cx: &LateContext<'_, '_>, expr: &Expr, op: &Expr, cast_from: T } } -impl LintPass for CastPass { - fn get_lints(&self) -> LintArray { - lint_array!( - CAST_PRECISION_LOSS, - CAST_SIGN_LOSS, - CAST_POSSIBLE_TRUNCATION, - CAST_POSSIBLE_WRAP, - CAST_LOSSLESS, - UNNECESSARY_CAST, - CAST_PTR_ALIGNMENT, - FN_TO_NUMERIC_CAST, - FN_TO_NUMERIC_CAST_WITH_TRUNCATION, - ) - } - - fn name(&self) -> &'static str { - "Casts" - } -} +declare_lint_pass!(Casts => [ + CAST_PRECISION_LOSS, + CAST_SIGN_LOSS, + CAST_POSSIBLE_TRUNCATION, + CAST_POSSIBLE_WRAP, + CAST_LOSSLESS, + UNNECESSARY_CAST, + CAST_PTR_ALIGNMENT, + FN_TO_NUMERIC_CAST, + FN_TO_NUMERIC_CAST_WITH_TRUNCATION, +]); // Check if the given type is either `core::ffi::c_void` or // one of the platform specific `libc::::c_void` of libc. -fn is_c_void<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'_>) -> bool { +fn is_c_void(cx: &LateContext<'_, '_>, ty: Ty<'_>) -> bool { if let ty::Adt(adt, _) = ty.sty { - let names = AbsolutePathPrinter { tcx }.print_def_path(adt.did, &[]).unwrap(); + let names = cx.get_def_path(adt.did); if names.is_empty() { return false; @@ -1160,7 +1108,7 @@ fn fp_ty_mantissa_nbits(typ: Ty<'_>) -> u32 { } } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Casts { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if let ExprKind::Cast(ref ex, _) = expr.node { let (cast_from, cast_to) = (cx.tables.expr_ty(ex), cx.tables.expr_ty(expr)); @@ -1262,7 +1210,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { if let Some(to_align) = cx.layout_of(to_ptr_ty.ty).ok().map(|a| a.align.abi); if from_align < to_align; // with c_void, we inherently need to trust the user - if !is_c_void(cx.tcx, from_ptr_ty.ty); + if !is_c_void(cx, from_ptr_ty.ty); then { span_lint( cx, @@ -1343,27 +1291,19 @@ declare_clippy_lint! { "usage of very complex types that might be better factored into `type` definitions" } -pub struct TypeComplexityPass { +pub struct TypeComplexity { threshold: u64, } -impl TypeComplexityPass { +impl TypeComplexity { pub fn new(threshold: u64) -> Self { Self { threshold } } } -impl LintPass for TypeComplexityPass { - fn get_lints(&self) -> LintArray { - lint_array!(TYPE_COMPLEXITY) - } - - fn name(&self) -> &'static str { - "TypeComplexityPass" - } -} +impl_lint_pass!(TypeComplexity => [TYPE_COMPLEXITY]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeComplexityPass { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeComplexity { fn check_fn( &mut self, cx: &LateContext<'a, 'tcx>, @@ -1413,7 +1353,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeComplexityPass { } } -impl<'a, 'tcx> TypeComplexityPass { +impl<'a, 'tcx> TypeComplexity { fn check_fndecl(&self, cx: &LateContext<'a, 'tcx>, decl: &'tcx FnDecl) { for arg in &decl.inputs { self.check_type(cx, arg); @@ -1519,17 +1459,7 @@ declare_clippy_lint! { "casting a character literal to u8" } -pub struct CharLitAsU8; - -impl LintPass for CharLitAsU8 { - fn get_lints(&self) -> LintArray { - lint_array!(CHAR_LIT_AS_U8) - } - - fn name(&self) -> &'static str { - "CharLiteralAsU8" - } -} +declare_lint_pass!(CharLitAsU8 => [CHAR_LIT_AS_U8]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CharLitAsU8 { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { @@ -1583,17 +1513,7 @@ declare_clippy_lint! { "a comparison with a maximum or minimum value that is always true or false" } -pub struct AbsurdExtremeComparisons; - -impl LintPass for AbsurdExtremeComparisons { - fn get_lints(&self) -> LintArray { - lint_array!(ABSURD_EXTREME_COMPARISONS) - } - - fn name(&self) -> &'static str { - "AbsurdExtremeComparisons" - } -} +declare_lint_pass!(AbsurdExtremeComparisons => [ABSURD_EXTREME_COMPARISONS]); enum ExtremeType { Minimum, @@ -1762,17 +1682,7 @@ declare_clippy_lint! { "a comparison involving an upcast which is always true or false" } -pub struct InvalidUpcastComparisons; - -impl LintPass for InvalidUpcastComparisons { - fn get_lints(&self) -> LintArray { - lint_array!(INVALID_UPCAST_COMPARISONS) - } - - fn name(&self) -> &'static str { - "InvalidUpcastComparisons" - } -} +declare_lint_pass!(InvalidUpcastComparisons => [INVALID_UPCAST_COMPARISONS]); #[derive(Copy, Clone, Debug, Eq)] enum FullInt { @@ -2011,17 +1921,7 @@ declare_clippy_lint! { "missing generalization over different hashers" } -pub struct ImplicitHasher; - -impl LintPass for ImplicitHasher { - fn get_lints(&self) -> LintArray { - lint_array!(IMPLICIT_HASHER) - } - - fn name(&self) -> &'static str { - "ImplicitHasher" - } -} +declare_lint_pass!(ImplicitHasher => [IMPLICIT_HASHER]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplicitHasher { #[allow(clippy::cast_possible_truncation, clippy::too_many_lines)] @@ -2366,17 +2266,7 @@ declare_clippy_lint! { "a cast of reference to a mutable pointer" } -pub struct RefToMut; - -impl LintPass for RefToMut { - fn get_lints(&self) -> LintArray { - lint_array!(CAST_REF_TO_MUT) - } - - fn name(&self) -> &'static str { - "RefToMut" - } -} +declare_lint_pass!(RefToMut => [CAST_REF_TO_MUT]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RefToMut { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { diff --git a/clippy_lints/src/unicode.rs b/clippy_lints/src/unicode.rs index 4d9e2f18650e..d96596bbb525 100644 --- a/clippy_lints/src/unicode.rs +++ b/clippy_lints/src/unicode.rs @@ -1,7 +1,7 @@ use crate::utils::{is_allowed, snippet, span_help_and_lint}; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use syntax::ast::LitKind; use syntax::source_map::Span; use unicode_normalization::UnicodeNormalization; @@ -58,18 +58,7 @@ declare_clippy_lint! { "using a unicode literal not in NFC normal form (see [unicode tr15](http://www.unicode.org/reports/tr15/) for further information)" } -#[derive(Copy, Clone)] -pub struct Unicode; - -impl LintPass for Unicode { - fn get_lints(&self) -> LintArray { - lint_array!(ZERO_WIDTH_SPACE, NON_ASCII_LITERAL, UNICODE_NOT_NFC) - } - - fn name(&self) -> &'static str { - "Unicode" - } -} +declare_lint_pass!(Unicode => [ZERO_WIDTH_SPACE, NON_ASCII_LITERAL, UNICODE_NOT_NFC]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Unicode { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { diff --git a/clippy_lints/src/unsafe_removed_from_name.rs b/clippy_lints/src/unsafe_removed_from_name.rs index 68ceaaac8a31..deeeefb88ab5 100644 --- a/clippy_lints/src/unsafe_removed_from_name.rs +++ b/clippy_lints/src/unsafe_removed_from_name.rs @@ -1,6 +1,6 @@ use crate::utils::span_lint; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use syntax::ast::*; use syntax::source_map::Span; use syntax::symbol::LocalInternedString; @@ -26,17 +26,7 @@ declare_clippy_lint! { "`unsafe` removed from API names on import" } -pub struct UnsafeNameRemoval; - -impl LintPass for UnsafeNameRemoval { - fn get_lints(&self) -> LintArray { - lint_array!(UNSAFE_REMOVED_FROM_NAME) - } - - fn name(&self) -> &'static str { - "UnsafeNameRemoval" - } -} +declare_lint_pass!(UnsafeNameRemoval => [UNSAFE_REMOVED_FROM_NAME]); impl EarlyLintPass for UnsafeNameRemoval { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { diff --git a/clippy_lints/src/unused_io_amount.rs b/clippy_lints/src/unused_io_amount.rs index 89f6873565a5..b3de0823bd45 100644 --- a/clippy_lints/src/unused_io_amount.rs +++ b/clippy_lints/src/unused_io_amount.rs @@ -1,7 +1,7 @@ use crate::utils::{is_try, match_qpath, match_trait_method, paths, span_lint}; use rustc::hir; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { /// **What it does:** Checks for unused written/read amount. @@ -30,17 +30,7 @@ declare_clippy_lint! { "unused written/read amount" } -pub struct UnusedIoAmount; - -impl LintPass for UnusedIoAmount { - fn get_lints(&self) -> LintArray { - lint_array!(UNUSED_IO_AMOUNT) - } - - fn name(&self) -> &'static str { - "UnusedIoAmount" - } -} +declare_lint_pass!(UnusedIoAmount => [UNUSED_IO_AMOUNT]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedIoAmount { fn check_stmt(&mut self, cx: &LateContext<'_, '_>, s: &hir::Stmt) { diff --git a/clippy_lints/src/unused_label.rs b/clippy_lints/src/unused_label.rs index d92511d999fb..73934adfb33f 100644 --- a/clippy_lints/src/unused_label.rs +++ b/clippy_lints/src/unused_label.rs @@ -2,7 +2,7 @@ use crate::utils::{in_macro, span_lint}; use rustc::hir; use rustc::hir::intravisit::{walk_expr, walk_fn, FnKind, NestedVisitorMap, Visitor}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_data_structures::fx::FxHashMap; use syntax::source_map::Span; use syntax::symbol::LocalInternedString; @@ -27,22 +27,12 @@ declare_clippy_lint! { "unused labels" } -pub struct UnusedLabel; - struct UnusedLabelVisitor<'a, 'tcx: 'a> { labels: FxHashMap, cx: &'a LateContext<'a, 'tcx>, } -impl LintPass for UnusedLabel { - fn get_lints(&self) -> LintArray { - lint_array!(UNUSED_LABEL) - } - - fn name(&self) -> &'static str { - "UnusedLable" - } -} +declare_lint_pass!(UnusedLabel => [UNUSED_LABEL]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedLabel { fn check_fn( diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs index 6b77e0f16faa..720795eace80 100644 --- a/clippy_lints/src/unwrap.rs +++ b/clippy_lints/src/unwrap.rs @@ -1,6 +1,6 @@ use if_chain::if_chain; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use crate::utils::{in_macro, match_type, paths, span_lint_and_then, usage::is_potentially_mutated}; use rustc::hir::intravisit::*; @@ -54,8 +54,6 @@ declare_clippy_lint! { "checks for calls of unwrap[_err]() that will always fail" } -pub struct Pass; - /// Visitor that keeps track of which variables are unwrappable. struct UnwrappableVariablesVisitor<'a, 'tcx: 'a> { unwrappables: Vec>, @@ -179,17 +177,9 @@ impl<'a, 'tcx: 'a> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> { } } -impl<'a> LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(PANICKING_UNWRAP, UNNECESSARY_UNWRAP) - } - - fn name(&self) -> &'static str { - "Unwrap" - } -} +declare_lint_pass!(Unwrap => [PANICKING_UNWRAP, UNNECESSARY_UNWRAP]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Unwrap { fn check_fn( &mut self, cx: &LateContext<'a, 'tcx>, diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index d3b011a3bd98..955239d4281f 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -5,7 +5,7 @@ use rustc::hir::*; use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass}; use rustc::ty; use rustc::ty::DefIdTree; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; use syntax_pos::symbol::keywords::SelfUpper; @@ -46,18 +46,7 @@ declare_clippy_lint! { "Unnecessary structure name repetition whereas `Self` is applicable" } -#[derive(Copy, Clone, Default)] -pub struct UseSelf; - -impl LintPass for UseSelf { - fn get_lints(&self) -> LintArray { - lint_array!(USE_SELF) - } - - fn name(&self) -> &'static str { - "UseSelf" - } -} +declare_lint_pass!(UseSelf => [USE_SELF]); const SEGMENTS_MSG: &str = "segments should be composed of at least 1 element"; diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index d0b7dd7e8089..4ddae1d01c13 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -7,7 +7,7 @@ use rustc::hir::intravisit::{NestedVisitorMap, Visitor}; use rustc::hir::{BindingAnnotation, Expr, ExprKind, Pat, PatKind, QPath, Stmt, StmtKind, TyKind}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintContext, LintPass}; use rustc::session::Session; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_data_structures::fx::FxHashMap; use syntax::ast::{Attribute, LitKind}; @@ -48,17 +48,7 @@ declare_clippy_lint! { "helper for writing lints" } -pub struct Pass; - -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(LINT_AUTHOR) - } - - fn name(&self) -> &'static str { - "Author" - } -} +declare_lint_pass!(Author => [LINT_AUTHOR]); fn prelude() { println!("if_chain! {{"); @@ -71,7 +61,7 @@ fn done() { println!("}}"); } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Author { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::Item) { if !has_attr(cx.sess(), &item.attrs) { return; diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 2c96d9a8b5aa..d759a98b6b40 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -109,7 +109,7 @@ define_Conf! { /// Lint: BLACKLISTED_NAME. The list of blacklisted names to lint about (blacklisted_names, "blacklisted_names", ["foo", "bar", "baz", "quux"] => Vec), /// Lint: COGNITIVE_COMPLEXITY. The maximum cognitive complexity a function can have - (cognitive_complexity_threshold, "cognitive_complexity_threshold", 25 => u64), + (cognitive_complexity_threshold, "cognitive_complexity_threshold", 500 => u64), /// DEPRECATED LINT: CYCLOMATIC_COMPLEXITY. Use the Cognitive Complexity lint instead. (cyclomatic_complexity_threshold, "cyclomatic_complexity_threshold", None => Option), /// Lint: DOC_MARKDOWN. The list of words this lint should not consider as identifiers needing ticks diff --git a/clippy_lints/src/utils/higher.rs b/clippy_lints/src/utils/higher.rs index bb4c18ea2bb6..6bb45b2c73f8 100644 --- a/clippy_lints/src/utils/higher.rs +++ b/clippy_lints/src/utils/higher.rs @@ -3,7 +3,7 @@ #![deny(clippy::missing_docs_in_private_items)] -use crate::utils::{is_expn_of, match_def_path, match_qpath, paths, resolve_node}; +use crate::utils::{is_expn_of, match_qpath, paths, resolve_node}; use if_chain::if_chain; use rustc::lint::LateContext; use rustc::{hir, ty}; @@ -216,11 +216,11 @@ pub fn vec_macro<'e>(cx: &LateContext<'_, '_>, expr: &'e hir::Expr) -> Option [DEEP_CODE_INSPECTION]); -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(DEEP_CODE_INSPECTION) - } - - fn name(&self) -> &'static str { - "DeepCodeInspector" - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DeepCodeInspector { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::Item) { if !has_attr(cx.sess(), &item.attrs) { return; @@ -153,6 +143,7 @@ fn has_attr(sess: &Session, attrs: &[Attribute]) -> bool { get_attr(sess, attrs, "dump").count() > 0 } +#[allow(clippy::cognitive_complexity)] #[allow(clippy::similar_names)] fn print_expr(cx: &LateContext<'_, '_>, expr: &hir::Expr, indent: usize) { let ind = " ".repeat(indent); @@ -415,6 +406,7 @@ fn print_item(cx: &LateContext<'_, '_>, item: &hir::Item) { } } +#[allow(clippy::cognitive_complexity)] #[allow(clippy::similar_names)] fn print_pat(cx: &LateContext<'_, '_>, pat: &hir::Pat, indent: usize) { let ind = " ".repeat(indent); diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index 343098ceeeea..375e3d2b3f4e 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -1,16 +1,13 @@ -use crate::utils::{ - match_def_path, match_type, paths, span_help_and_lint, span_lint, span_lint_and_sugg, walk_ptrs_ty, -}; +use crate::utils::{match_type, paths, span_help_and_lint, span_lint, walk_ptrs_ty}; use if_chain::if_chain; use rustc::hir; use rustc::hir::def::Def; use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc::hir::*; use rustc::lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint, impl_lint_pass}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_errors::Applicability; -use syntax::ast::{Crate as AstCrate, Ident, ItemKind, Name}; +use syntax::ast::{Crate as AstCrate, ItemKind, Name}; use syntax::source_map::Span; use syntax::symbol::LocalInternedString; @@ -34,8 +31,8 @@ declare_clippy_lint! { /// putting a lint to a `LintPass::get_lints()`'s return, the compiler will not /// know the name of the lint. /// - /// **Known problems:** Only checks for lints associated using the `lint_array!` - /// macro. + /// **Known problems:** Only checks for lints associated using the + /// `declare_lint_pass!`, `impl_lint_pass!`, and `lint_array!` macros. /// /// **Example:** /// ```rust @@ -43,30 +40,14 @@ declare_clippy_lint! { /// declare_lint! { pub LINT_2, ... } /// declare_lint! { pub FORGOTTEN_LINT, ... } /// // ... - /// pub struct Pass; - /// impl LintPass for Pass { - /// fn get_lints(&self) -> LintArray { - /// lint_array![LINT_1, LINT_2] - /// // missing FORGOTTEN_LINT - /// } - /// } + /// declare_lint_pass!(Pass => [LINT_1, LINT_2]); + /// // missing FORGOTTEN_LINT /// ``` pub LINT_WITHOUT_LINT_PASS, internal, "declaring a lint without associating it in a LintPass" } -declare_clippy_lint! { - /// **What it does:** Checks for the presence of the default hash types "HashMap" or "HashSet" - /// and recommends the FxHash* variants. - /// - /// **Why is this bad?** The FxHash variants have better performance - /// and we don't need any collision prevention in clippy. - pub DEFAULT_HASH_TYPES, - internal, - "forbid HashMap and HashSet and suggest the FxHash* variants" -} - declare_clippy_lint! { /// **What it does:** Checks for calls to `cx.span_lint*` and suggests to use the `utils::*` /// variant of the function. @@ -91,20 +72,9 @@ declare_clippy_lint! { "usage of the lint functions of the compiler instead of the utils::* variant" } -#[derive(Copy, Clone)] -pub struct Clippy; +declare_lint_pass!(ClippyLintsInternal => [CLIPPY_LINTS_INTERNAL]); -impl LintPass for Clippy { - fn get_lints(&self) -> LintArray { - lint_array!(CLIPPY_LINTS_INTERNAL) - } - - fn name(&self) -> &'static str { - "ClippyLintsInternal" - } -} - -impl EarlyLintPass for Clippy { +impl EarlyLintPass for ClippyLintsInternal { fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &AstCrate) { if let Some(utils) = krate.module.items.iter().find(|item| item.ident.name == "utils") { if let ItemKind::Mod(ref utils_mod) = utils.node { @@ -139,14 +109,7 @@ pub struct LintWithoutLintPass { registered_lints: FxHashSet, } -impl LintPass for LintWithoutLintPass { - fn get_lints(&self) -> LintArray { - lint_array!(LINT_WITHOUT_LINT_PASS) - } - fn name(&self) -> &'static str { - "LintWithoutLintPass" - } -} +impl_lint_pass!(LintWithoutLintPass => [LINT_WITHOUT_LINT_PASS]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LintWithoutLintPass { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { @@ -158,13 +121,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LintWithoutLintPass { if_chain! { if let hir::TraitRef{path, ..} = trait_ref; if let Def::Trait(def_id) = path.def; - if match_def_path(cx.tcx, def_id, &paths::LINT_PASS); + if cx.match_def_path(def_id, &paths::LINT_PASS); then { let mut collector = LintCollector { output: &mut self.registered_lints, cx, }; - let body_id = cx.tcx.hir().body_owned_by(impl_item_refs[0].id.hir_id); + let body_id = cx.tcx.hir().body_owned_by( + impl_item_refs + .iter() + .find(|iiref| iiref.ident.as_str() == "get_lints") + .expect("LintPass needs to implement get_lints") + .id.hir_id + ); collector.visit_expr(&cx.tcx.hir().body(body_id).value); } } @@ -210,7 +179,7 @@ fn is_lint_ref_type<'tcx>(cx: &LateContext<'_, 'tcx>, ty: &Ty) -> bool { { if let TyKind::Path(ref path) = inner.node { if let Def::Struct(def_id) = cx.tables.qpath_def(path, inner.hir_id) { - return match_def_path(cx.tcx, def_id, &paths::LINT); + return cx.match_def_path(def_id, &paths::LINT); } } } @@ -238,51 +207,6 @@ impl<'a, 'tcx: 'a> Visitor<'tcx> for LintCollector<'a, 'tcx> { } } -pub struct DefaultHashTypes { - map: FxHashMap, -} - -impl DefaultHashTypes { - pub fn default() -> Self { - let mut map = FxHashMap::default(); - map.insert("HashMap".to_string(), "FxHashMap".to_string()); - map.insert("HashSet".to_string(), "FxHashSet".to_string()); - Self { map } - } -} - -impl LintPass for DefaultHashTypes { - fn get_lints(&self) -> LintArray { - lint_array!(DEFAULT_HASH_TYPES) - } - - fn name(&self) -> &'static str { - "DefaultHashType" - } -} - -impl EarlyLintPass for DefaultHashTypes { - fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: Ident) { - let ident_string = ident.to_string(); - if let Some(replace) = self.map.get(&ident_string) { - let msg = format!( - "Prefer {} over {}, it has better performance \ - and we don't need any collision prevention in clippy", - replace, ident_string - ); - span_lint_and_sugg( - cx, - DEFAULT_HASH_TYPES, - ident.span, - &msg, - "use", - replace.to_string(), - Applicability::MaybeIncorrect, // FxHashMap, ... needs another import - ); - } - } -} - #[derive(Clone, Default)] pub struct CompilerLintFunctions { map: FxHashMap, @@ -300,15 +224,7 @@ impl CompilerLintFunctions { } } -impl LintPass for CompilerLintFunctions { - fn get_lints(&self) -> LintArray { - lint_array!(COMPILER_LINT_FUNCTIONS) - } - - fn name(&self) -> &'static str { - "CompileLintFunctions" - } -} +impl_lint_pass!(CompilerLintFunctions => [COMPILER_LINT_FUNCTIONS]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CompilerLintFunctions { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { @@ -325,7 +241,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CompilerLintFunctions { COMPILER_LINT_FUNCTIONS, path.ident.span, "usage of a compiler lint function", - &format!("Please use the Clippy variant of this function: `{}`", sugg), + &format!("please use the Clippy variant of this function: `{}`", sugg), ); } } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 46aec1fa343f..e95acd343bf4 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -24,10 +24,8 @@ use if_chain::if_chain; use matches::matches; use rustc::hir; use rustc::hir::def::Def; -use rustc::hir::def_id::CrateNum; use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc::hir::intravisit::{NestedVisitorMap, Visitor}; -use rustc::hir::map::{DefPathData, DisambiguatedDefPathData}; use rustc::hir::Node; use rustc::hir::*; use rustc::lint::{LateContext, Level, Lint, LintContext}; @@ -43,7 +41,7 @@ use rustc_errors::Applicability; use syntax::ast::{self, LitKind}; use syntax::attr; use syntax::source_map::{Span, DUMMY_SP}; -use syntax::symbol::{keywords, LocalInternedString, Symbol}; +use syntax::symbol::{keywords, Symbol}; use crate::reexport::*; @@ -95,139 +93,24 @@ pub fn in_macro(span: Span) -> bool { span.ctxt().outer().expn_info().is_some() } -/// Used to store the absolute path to a type. -/// -/// See `match_def_path` for usage. -pub struct AbsolutePathPrinter<'a, 'tcx> { - pub tcx: TyCtxt<'a, 'tcx, 'tcx>, -} - -use rustc::ty::print::Printer; - -#[allow(clippy::diverging_sub_expression)] -impl<'tcx> Printer<'tcx, 'tcx> for AbsolutePathPrinter<'_, 'tcx> { - type Error = !; - - type Path = Vec; - type Region = (); - type Type = (); - type DynExistential = (); - - fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> { - self.tcx - } - - fn print_region(self, _region: ty::Region<'_>) -> Result { - Ok(()) - } - - fn print_type(self, _ty: Ty<'tcx>) -> Result { - Ok(()) - } - - fn print_dyn_existential( - self, - _predicates: &'tcx ty::List>, - ) -> Result { - Ok(()) - } - - fn path_crate(self, cnum: CrateNum) -> Result { - Ok(vec![self.tcx.original_crate_name(cnum).as_str()]) - } - - fn path_qualified( - self, - self_ty: Ty<'tcx>, - trait_ref: Option>, - ) -> Result { - if trait_ref.is_none() { - if let ty::Adt(def, substs) = self_ty.sty { - return self.print_def_path(def.did, substs); - } - } - - // This shouldn't ever be needed, but just in case: - Ok(vec![match trait_ref { - Some(trait_ref) => Symbol::intern(&format!("{:?}", trait_ref)).as_str(), - None => Symbol::intern(&format!("<{}>", self_ty)).as_str(), - }]) - } - - fn path_append_impl( - self, - print_prefix: impl FnOnce(Self) -> Result, - _disambiguated_data: &DisambiguatedDefPathData, - self_ty: Ty<'tcx>, - trait_ref: Option>, - ) -> Result { - let mut path = print_prefix(self)?; - - // This shouldn't ever be needed, but just in case: - path.push(match trait_ref { - Some(trait_ref) => Symbol::intern(&format!("", trait_ref, self_ty)).as_str(), - None => Symbol::intern(&format!("", self_ty)).as_str(), - }); - - Ok(path) - } - - fn path_append( - self, - print_prefix: impl FnOnce(Self) -> Result, - disambiguated_data: &DisambiguatedDefPathData, - ) -> Result { - let mut path = print_prefix(self)?; - - // Skip `::{{constructor}}` on tuple/unit structs. - if let DefPathData::Ctor = disambiguated_data.data { - return Ok(path); +// If the snippet is empty, it's an attribute that was inserted during macro +// expansion and we want to ignore those, because they could come from external +// sources that the user has no control over. +// For some reason these attributes don't have any expansion info on them, so +// we have to check it this way until there is a better way. +pub fn is_present_in_source<'a, T: LintContext<'a>>(cx: &T, span: Span) -> bool { + if let Some(snippet) = snippet_opt(cx, span) { + if snippet.is_empty() { + return false; } - - path.push(disambiguated_data.data.as_interned_str().as_str()); - Ok(path) - } - - fn path_generic_args( - self, - print_prefix: impl FnOnce(Self) -> Result, - _args: &[Kind<'tcx>], - ) -> Result { - print_prefix(self) } -} - -/// Checks if a `DefId`'s path matches the given absolute type path usage. -/// -/// # Examples -/// ```rust,ignore -/// match_def_path(cx.tcx, id, &["core", "option", "Option"]) -/// ``` -/// -/// See also the `paths` module. -pub fn match_def_path<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, path: &[&str]) -> bool { - let names = get_def_path(tcx, def_id); - - names.len() == path.len() && names.into_iter().zip(path.iter()).all(|(a, &b)| *a == *b) -} - -/// Gets the absolute path of `def_id` as a vector of `&str`. -/// -/// # Examples -/// ```rust,ignore -/// let def_path = get_def_path(tcx, def_id); -/// if let &["core", "option", "Option"] = &def_path[..] { -/// // The given `def_id` is that of an `Option` type -/// }; -/// ``` -pub fn get_def_path<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Vec { - AbsolutePathPrinter { tcx }.print_def_path(def_id, &[]).unwrap() + true } /// Checks if type is struct, enum or union type with the given def path. pub fn match_type(cx: &LateContext<'_, '_>, ty: Ty<'_>, path: &[&str]) -> bool { match ty.sty { - ty::Adt(adt, _) => match_def_path(cx.tcx, adt.did, path), + ty::Adt(adt, _) => cx.match_def_path(adt.did, path), _ => false, } } @@ -237,7 +120,7 @@ pub fn match_trait_method(cx: &LateContext<'_, '_>, expr: &Expr, path: &[&str]) let def_id = cx.tables.type_dependent_def_id(expr.hir_id).unwrap(); let trt_id = cx.tcx.trait_of_item(def_id); if let Some(trt_id) = trt_id { - match_def_path(cx.tcx, trt_id, path) + cx.match_def_path(trt_id, path) } else { false } @@ -859,6 +742,19 @@ 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) } +/// Checks if an expression is constructing a tuple-like enum variant or struct +pub fn is_ctor_function(cx: &LateContext<'_, '_>, expr: &Expr) -> bool { + if let ExprKind::Call(ref fun, _) = expr.node { + if let ExprKind::Path(ref qp) = fun.node { + return matches!( + cx.tables.qpath_def(qp, fun.hir_id), + def::Def::Variant(..) | def::Def::Ctor(..) + ); + } + } + false +} + /// Returns `true` if a pattern is refutable. pub fn is_refutable(cx: &LateContext<'_, '_>, pat: &Pat) -> bool { fn is_enum_variant(cx: &LateContext<'_, '_>, qpath: &QPath, id: HirId) -> bool { @@ -1120,7 +1016,7 @@ pub fn has_iter_method(cx: &LateContext<'_, '_>, probably_ref_ty: Ty<'_>) -> Opt }; for path in &INTO_ITER_COLLECTIONS { - if match_def_path(cx.tcx, def_id, path) { + if cx.match_def_path(def_id, path) { return Some(path.last().unwrap()); } } diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index 9b8b2372c53b..2422a7060cd1 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -4,7 +4,7 @@ use if_chain::if_chain; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::ty::{self, Ty}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; use syntax::source_map::Span; @@ -25,20 +25,9 @@ declare_clippy_lint! { "useless `vec!`" } -#[derive(Copy, Clone, Debug)] -pub struct Pass; +declare_lint_pass!(UselessVec => [USELESS_VEC]); -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(USELESS_VEC) - } - - fn name(&self) -> &'static str { - "UselessVec" - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessVec { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { // search for `&vec![_]` expressions where the adjusted type is `&[_]` if_chain! { diff --git a/clippy_lints/src/wildcard_dependencies.rs b/clippy_lints/src/wildcard_dependencies.rs index 30bd2177ca91..b2a66b6d5a44 100644 --- a/clippy_lints/src/wildcard_dependencies.rs +++ b/clippy_lints/src/wildcard_dependencies.rs @@ -1,6 +1,6 @@ use crate::utils::span_lint; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use syntax::{ast::*, source_map::DUMMY_SP}; use cargo_metadata; @@ -27,19 +27,9 @@ declare_clippy_lint! { "wildcard dependencies being used" } -pub struct Pass; +declare_lint_pass!(WildcardDependencies => [WILDCARD_DEPENDENCIES]); -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(WILDCARD_DEPENDENCIES) - } - - fn name(&self) -> &'static str { - "WildcardDependencies" - } -} - -impl EarlyLintPass for Pass { +impl EarlyLintPass for WildcardDependencies { fn check_crate(&mut self, cx: &EarlyContext<'_>, _: &Crate) { let metadata = if let Ok(metadata) = cargo_metadata::MetadataCommand::new().no_deps().exec() { metadata diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index c0ffb16c3574..9f4ebdec7143 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -1,6 +1,6 @@ use crate::utils::{snippet_with_applicability, span_lint, span_lint_and_sugg}; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; use std::borrow::Cow; use syntax::ast::*; @@ -168,29 +168,18 @@ declare_clippy_lint! { "writing a literal with a format string" } -#[derive(Copy, Clone, Debug)] -pub struct Pass; +declare_lint_pass!(Write => [ + PRINT_WITH_NEWLINE, + PRINTLN_EMPTY_STRING, + PRINT_STDOUT, + USE_DEBUG, + PRINT_LITERAL, + WRITE_WITH_NEWLINE, + WRITELN_EMPTY_STRING, + WRITE_LITERAL +]); -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!( - PRINT_WITH_NEWLINE, - PRINTLN_EMPTY_STRING, - PRINT_STDOUT, - USE_DEBUG, - PRINT_LITERAL, - WRITE_WITH_NEWLINE, - WRITELN_EMPTY_STRING, - WRITE_LITERAL - ) - } - - fn name(&self) -> &'static str { - "Write" - } -} - -impl EarlyLintPass for Pass { +impl EarlyLintPass for Write { fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &Mac) { if mac.node.path == "println" { span_lint(cx, PRINT_STDOUT, mac.span, "use of `println!`"); diff --git a/clippy_lints/src/zero_div_zero.rs b/clippy_lints/src/zero_div_zero.rs index de13816f66fd..094cb627dc3a 100644 --- a/clippy_lints/src/zero_div_zero.rs +++ b/clippy_lints/src/zero_div_zero.rs @@ -3,7 +3,7 @@ use crate::utils::span_help_and_lint; use if_chain::if_chain; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { /// **What it does:** Checks for `0.0 / 0.0`. @@ -22,19 +22,9 @@ declare_clippy_lint! { "usage of `0.0 / 0.0` to obtain NaN instead of std::f32::NaN or std::f64::NaN" } -pub struct Pass; +declare_lint_pass!(ZeroDiv => [ZERO_DIVIDED_BY_ZERO]); -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(ZERO_DIVIDED_BY_ZERO) - } - - fn name(&self) -> &'static str { - "ZeroDiv" - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ZeroDiv { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { // check for instances of 0.0/0.0 if_chain! { diff --git a/doc/adding_lints.md b/doc/adding_lints.md index a45551dbf9c5..5781ab7f9999 100644 --- a/doc/adding_lints.md +++ b/doc/adding_lints.md @@ -116,7 +116,7 @@ where all the lint code is. We are going to call the file ```rust use rustc::lint::{LintArray, LintPass, EarlyLintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_lint_pass, declare_tool_lint}; ``` The next step is to provide a lint declaration. Lints are declared using the @@ -147,22 +147,9 @@ lint pass: // .. imports and lint declaration .. -#[derive(Copy, Clone)] -pub struct FooFunctionsPass; - -impl LintPass for FooFunctionsPass { - fn get_lints(&self) -> LintArray { - lint_array!( - FOO_FUNCTIONS, - ) - } - - fn name(&self) -> &'static str { - "FooFunctions" - } -} +declare_lint_pass!(FooFunctions => [FOO_FUNCTIONS]); -impl EarlyLintPass for FooFunctionsPass {} +impl EarlyLintPass for FooFunctions {} ``` Don't worry about the `name` method here. As long as it includes the name of the @@ -176,7 +163,7 @@ will have to register our lint pass manually in the `register_plugins` function in `clippy_lints/src/lib.rs`: ```rust -reg.register_early_lint_pass(box foo_functions::FooFunctionsPass); +reg.register_early_lint_pass(box foo_functions::FooFunctions); ``` This should fix the `unknown clippy lint: clippy::foo_functions` error that we @@ -211,10 +198,10 @@ use rustc::{declare_tool_lint, lint_array}; With UI tests and the lint declaration in place, we can start working on the implementation of the lint logic. -Let's start by implementing the `EarlyLintPass` for our `FooFunctionsPass`: +Let's start by implementing the `EarlyLintPass` for our `FooFunctions`: ```rust -impl EarlyLintPass for FooFunctionsPass { +impl EarlyLintPass for FooFunctions { fn check_fn(&mut self, cx: &EarlyContext<'_>, fn_kind: FnKind<'_>, _: &FnDecl, span: Span, _: NodeId) { // TODO: Emit lint here } @@ -236,7 +223,7 @@ provide an extra help message and we can't really suggest a better name automatically. This is how it looks: ```rust -impl EarlyLintPass for Pass { +impl EarlyLintPass for FooFunctions { fn check_fn(&mut self, cx: &EarlyContext<'_>, _: FnKind<'_>, _: &FnDecl, span: Span, _: NodeId) { span_help_and_lint( cx, @@ -263,7 +250,7 @@ Both provide access to the name of the function/method via an [`Ident`][ident]. With that we can expand our `check_fn` method to: ```rust -impl EarlyLintPass for Pass { +impl EarlyLintPass for FooFunctions { fn check_fn(&mut self, cx: &EarlyContext<'_>, fn_kind: FnKind<'_>, _: &FnDecl, span: Span, _: NodeId) { if is_foo_fn(fn_kind) { span_help_and_lint( @@ -304,16 +291,6 @@ running `cargo test` should produce the expected output. Remember to run `cargo test` (as opposed to `cargo uitest`) will also ensure that our lint implementation is not violating any Clippy lints itself. -If you are still following the example, you will see that `FooFunctionsPass` -violates a Clippy lint. So we are going to rename that struct to just `Pass`: - -```rust -#[derive(Copy, Clone)] -pub struct Pass; - -impl LintPass for Pass { /* .. */ } -``` - That should be it for the lint implementation. Running `cargo test` should now pass. @@ -394,6 +371,7 @@ Before submitting your PR make sure you followed all of the basic requirements: - [ ] `cargo test` passes locally - [ ] Executed `util/dev update_lints` - [ ] Added lint documentation +- [ ] Run `cargo fmt` ### Cheatsheet diff --git a/tests/compile-test.rs b/tests/compile-test.rs index bafd64e934f3..56b50678a600 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -46,9 +46,32 @@ fn config(mode: &str, dir: PathBuf) -> compiletest::Config { config.run_lib_path = rustc_lib_path(); config.compile_lib_path = rustc_lib_path(); } + + // When we'll want to use `extern crate ..` for a dependency that is used + // both by the crate and the compiler itself, we can't simply pass -L flags + // as we'll get a duplicate matching versions. Instead, disambiguate with + // `--extern dep=path`. + // See https://github.com/rust-lang/rust-clippy/issues/4015. + let needs_disambiguation = ["serde"]; + // This assumes that deps are compiled (they are for Cargo integration tests). + let deps = std::fs::read_dir(host_libs().join("deps")).unwrap(); + let disambiguated = deps + .filter_map(|dep| { + let path = dep.ok()?.path(); + let name = path.file_name()?.to_string_lossy(); + // NOTE: This only handles a single dep + // https://github.com/laumann/compiletest-rs/issues/101 + needs_disambiguation + .iter() + .find(|dep| name.starts_with(&format!("lib{}-", dep))) + .map(|dep| format!("--extern {}={}", dep, path.display())) + }) + .collect::>(); + config.target_rustcflags = Some(format!( - "-L {0} -L {0}/deps -Dwarnings -Zui-testing", - host_libs().display() + "-L {0} -L {0}/deps -Dwarnings -Zui-testing {1}", + host_libs().display(), + disambiguated.join(" ") )); config.mode = cfg_mode; @@ -67,13 +90,6 @@ fn config(mode: &str, dir: PathBuf) -> compiletest::Config { config } -fn run_mode(mode: &str, dir: PathBuf) { - let cfg = config(mode, dir); - // clean rmeta data, otherwise "cargo check; cargo test" fails (#2896) - cfg.clean_rmeta(); - compiletest::run_tests(&cfg); -} - #[allow(clippy::identity_conversion)] fn run_ui_toml_tests(config: &compiletest::Config, mut tests: Vec) -> Result { let mut result = true; @@ -131,9 +147,28 @@ fn prepare_env() { //set_var("RUST_BACKTRACE", "0"); } +fn run_ui_tests() { + let mut cfg = config("ui", "tests/ui".into()); + // clean rmeta data, otherwise "cargo check; cargo test" fails (#2896) + cfg.clean_rmeta(); + + let default_flags = { + if let Some(flags) = cfg.target_rustcflags { + flags + } else { + "".to_string() + } + }; + let new_flags = format!("{} -A clippy::cognitive_complexity", default_flags); + cfg.target_rustcflags = Some(new_flags); + + compiletest::run_tests(&cfg); +} + #[test] fn compile_test() { prepare_env(); - run_mode("ui", "tests/ui".into()); + run_ui_tests(); + // run_mode("ui", "tests/ui".into()); run_ui_toml(); } diff --git a/tests/ui/assertions_on_constants.rs b/tests/ui/assertions_on_constants.rs index 0d2953c7ed81..aee6cc505abd 100644 --- a/tests/ui/assertions_on_constants.rs +++ b/tests/ui/assertions_on_constants.rs @@ -18,6 +18,8 @@ fn main() { assert!(C); debug_assert!(true); + // Don't lint this, since there is no better way for expressing "Only panic in debug mode". + debug_assert!(false); // #3948 assert_const!(3); assert_const!(-1); } diff --git a/tests/ui/assertions_on_constants.stderr b/tests/ui/assertions_on_constants.stderr index adfa326abacb..c22da856975c 100644 --- a/tests/ui/assertions_on_constants.stderr +++ b/tests/ui/assertions_on_constants.stderr @@ -1,4 +1,4 @@ -error: assert!(true) will be optimized out by the compiler +error: `assert!(true)` will be optimized out by the compiler --> $DIR/assertions_on_constants.rs:9:5 | LL | assert!(true); @@ -7,15 +7,15 @@ LL | assert!(true); = note: `-D clippy::assertions-on-constants` implied by `-D warnings` = help: remove it -error: assert!(false) should probably be replaced +error: `assert!(false)` should probably be replaced --> $DIR/assertions_on_constants.rs:10:5 | LL | assert!(false); | ^^^^^^^^^^^^^^^ | - = help: use panic!() or unreachable!() + = help: use `panic!()` or `unreachable!()` -error: assert!(true) will be optimized out by the compiler +error: `assert!(true)` will be optimized out by the compiler --> $DIR/assertions_on_constants.rs:11:5 | LL | assert!(true, "true message"); @@ -23,15 +23,15 @@ LL | assert!(true, "true message"); | = help: remove it -error: assert!(false) should probably be replaced +error: `assert!(false)` should probably be replaced --> $DIR/assertions_on_constants.rs:12:5 | LL | assert!(false, "false message"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: use panic!() or unreachable!() + = help: use `panic!()` or `unreachable!()` -error: assert!(const: true) will be optimized out by the compiler +error: `assert!(true)` will be optimized out by the compiler --> $DIR/assertions_on_constants.rs:15:5 | LL | assert!(B); @@ -39,15 +39,15 @@ LL | assert!(B); | = help: remove it -error: assert!(const: false) should probably be replaced +error: `assert!(false)` should probably be replaced --> $DIR/assertions_on_constants.rs:18:5 | LL | assert!(C); | ^^^^^^^^^^^ | - = help: use panic!() or unreachable!() + = help: use `panic!()` or `unreachable!()` -error: assert!(true) will be optimized out by the compiler +error: `assert!(true)` will be optimized out by the compiler --> $DIR/assertions_on_constants.rs:20:5 | LL | debug_assert!(true); diff --git a/tests/ui/auxiliary/proc_macro_derive.rs b/tests/ui/auxiliary/proc_macro_derive.rs index d527aac6fa12..08b993173029 100644 --- a/tests/ui/auxiliary/proc_macro_derive.rs +++ b/tests/ui/auxiliary/proc_macro_derive.rs @@ -9,7 +9,12 @@ use proc_macro::{quote, TokenStream}; #[proc_macro_derive(DeriveSomething)] pub fn derive(_: TokenStream) -> TokenStream { + // Shound not trigger `used_underscore_binding` + let _inside_derive = 1; + assert_eq!(_inside_derive, _inside_derive); + let output = quote! { + // Should not trigger `useless_attribute` #[allow(dead_code)] extern crate clippy_lints; }; diff --git a/tests/ui/bool_comparison.fixed b/tests/ui/bool_comparison.fixed new file mode 100644 index 000000000000..0bd73ec2c104 --- /dev/null +++ b/tests/ui/bool_comparison.fixed @@ -0,0 +1,113 @@ +// run-rustfix + +#[warn(clippy::bool_comparison)] +fn main() { + let x = true; + if x { + "yes" + } else { + "no" + }; + if !x { + "yes" + } else { + "no" + }; + if x { + "yes" + } else { + "no" + }; + if !x { + "yes" + } else { + "no" + }; + if !x { + "yes" + } else { + "no" + }; + if x { + "yes" + } else { + "no" + }; + if !x { + "yes" + } else { + "no" + }; + if x { + "yes" + } else { + "no" + }; + if !x { + "yes" + } else { + "no" + }; + if x { + "yes" + } else { + "no" + }; + if x { + "yes" + } else { + "no" + }; + if !x { + "yes" + } else { + "no" + }; + let y = true; + if !x & y { + "yes" + } else { + "no" + }; + if x & !y { + "yes" + } else { + "no" + }; +} + +#[allow(dead_code)] +fn issue3703() { + struct Foo; + impl PartialEq for Foo { + fn eq(&self, _: &bool) -> bool { + true + } + } + impl PartialEq for bool { + fn eq(&self, _: &Foo) -> bool { + true + } + } + impl PartialOrd for Foo { + fn partial_cmp(&self, _: &bool) -> Option { + None + } + } + impl PartialOrd for bool { + fn partial_cmp(&self, _: &Foo) -> Option { + None + } + } + + if Foo == true {} + if true == Foo {} + if Foo != true {} + if true != Foo {} + if Foo == false {} + if false == Foo {} + if Foo != false {} + if false != Foo {} + if Foo < false {} + if false < Foo {} +} diff --git a/tests/ui/bool_comparison.rs b/tests/ui/bool_comparison.rs index 36d31aa043bb..74f504edfd06 100644 --- a/tests/ui/bool_comparison.rs +++ b/tests/ui/bool_comparison.rs @@ -1,3 +1,5 @@ +// run-rustfix + #[warn(clippy::bool_comparison)] fn main() { let x = true; diff --git a/tests/ui/bool_comparison.stderr b/tests/ui/bool_comparison.stderr index 2d473d91d668..2aa070a00f30 100644 --- a/tests/ui/bool_comparison.stderr +++ b/tests/ui/bool_comparison.stderr @@ -1,5 +1,5 @@ error: equality checks against true are unnecessary - --> $DIR/bool_comparison.rs:4:8 + --> $DIR/bool_comparison.rs:6:8 | LL | if x == true { | ^^^^^^^^^ help: try simplifying it as shown: `x` @@ -7,79 +7,79 @@ LL | if x == true { = note: `-D clippy::bool-comparison` implied by `-D warnings` error: equality checks against false can be replaced by a negation - --> $DIR/bool_comparison.rs:9:8 + --> $DIR/bool_comparison.rs:11:8 | LL | if x == false { | ^^^^^^^^^^ help: try simplifying it as shown: `!x` error: equality checks against true are unnecessary - --> $DIR/bool_comparison.rs:14:8 + --> $DIR/bool_comparison.rs:16:8 | LL | if true == x { | ^^^^^^^^^ help: try simplifying it as shown: `x` error: equality checks against false can be replaced by a negation - --> $DIR/bool_comparison.rs:19:8 + --> $DIR/bool_comparison.rs:21:8 | LL | if false == x { | ^^^^^^^^^^ help: try simplifying it as shown: `!x` error: inequality checks against true can be replaced by a negation - --> $DIR/bool_comparison.rs:24:8 + --> $DIR/bool_comparison.rs:26:8 | LL | if x != true { | ^^^^^^^^^ help: try simplifying it as shown: `!x` error: inequality checks against false are unnecessary - --> $DIR/bool_comparison.rs:29:8 + --> $DIR/bool_comparison.rs:31:8 | LL | if x != false { | ^^^^^^^^^^ help: try simplifying it as shown: `x` error: inequality checks against true can be replaced by a negation - --> $DIR/bool_comparison.rs:34:8 + --> $DIR/bool_comparison.rs:36:8 | LL | if true != x { | ^^^^^^^^^ help: try simplifying it as shown: `!x` error: inequality checks against false are unnecessary - --> $DIR/bool_comparison.rs:39:8 + --> $DIR/bool_comparison.rs:41:8 | LL | if false != x { | ^^^^^^^^^^ help: try simplifying it as shown: `x` error: less than comparison against true can be replaced by a negation - --> $DIR/bool_comparison.rs:44:8 + --> $DIR/bool_comparison.rs:46:8 | LL | if x < true { | ^^^^^^^^ help: try simplifying it as shown: `!x` error: greater than checks against false are unnecessary - --> $DIR/bool_comparison.rs:49:8 + --> $DIR/bool_comparison.rs:51:8 | LL | if false < x { | ^^^^^^^^^ help: try simplifying it as shown: `x` error: greater than checks against false are unnecessary - --> $DIR/bool_comparison.rs:54:8 + --> $DIR/bool_comparison.rs:56:8 | LL | if x > false { | ^^^^^^^^^ help: try simplifying it as shown: `x` error: less than comparison against true can be replaced by a negation - --> $DIR/bool_comparison.rs:59:8 + --> $DIR/bool_comparison.rs:61:8 | LL | if true > x { | ^^^^^^^^ help: try simplifying it as shown: `!x` error: order comparisons between booleans can be simplified - --> $DIR/bool_comparison.rs:65:8 + --> $DIR/bool_comparison.rs:67:8 | LL | if x < y { | ^^^^^ help: try simplifying it as shown: `!x & y` error: order comparisons between booleans can be simplified - --> $DIR/bool_comparison.rs:70:8 + --> $DIR/bool_comparison.rs:72:8 | LL | if x > y { | ^^^^^ help: try simplifying it as shown: `x & !y` diff --git a/tests/ui/cast.rs b/tests/ui/cast.rs index ab5f9bb4e9d2..914296644e6b 100644 --- a/tests/ui/cast.rs +++ b/tests/ui/cast.rs @@ -2,8 +2,7 @@ clippy::cast_precision_loss, clippy::cast_possible_truncation, clippy::cast_sign_loss, - clippy::cast_possible_wrap, - clippy::cast_lossless + clippy::cast_possible_wrap )] #[allow(clippy::no_effect, clippy::unnecessary_operation)] fn main() { @@ -32,10 +31,6 @@ fn main() { 1u32 as i32; 1u64 as i64; 1usize as isize; - // Test clippy::cast_lossless with casts from floating-point types - 1.0f32 as f64; - // Test clippy::cast_lossless with an expression wrapped in parens - (1u8 + 1u8) as u16; // Test clippy::cast_sign_loss 1i32 as u32; -1i32 as u32; diff --git a/tests/ui/cast.stderr b/tests/ui/cast.stderr index 9923d35832e2..28bcfacd8589 100644 --- a/tests/ui/cast.stderr +++ b/tests/ui/cast.stderr @@ -1,5 +1,5 @@ error: casting i32 to f32 causes a loss of precision (i32 is 32 bits wide, but f32's mantissa is only 23 bits wide) - --> $DIR/cast.rs:12:5 + --> $DIR/cast.rs:11:5 | LL | x0 as f32; | ^^^^^^^^^ @@ -7,37 +7,37 @@ LL | x0 as f32; = note: `-D clippy::cast-precision-loss` implied by `-D warnings` error: casting i64 to f32 causes a loss of precision (i64 is 64 bits wide, but f32's mantissa is only 23 bits wide) - --> $DIR/cast.rs:14:5 + --> $DIR/cast.rs:13:5 | LL | x1 as f32; | ^^^^^^^^^ error: casting i64 to f64 causes a loss of precision (i64 is 64 bits wide, but f64's mantissa is only 52 bits wide) - --> $DIR/cast.rs:15:5 + --> $DIR/cast.rs:14:5 | LL | x1 as f64; | ^^^^^^^^^ error: casting u32 to f32 causes a loss of precision (u32 is 32 bits wide, but f32's mantissa is only 23 bits wide) - --> $DIR/cast.rs:17:5 + --> $DIR/cast.rs:16:5 | LL | x2 as f32; | ^^^^^^^^^ error: casting u64 to f32 causes a loss of precision (u64 is 64 bits wide, but f32's mantissa is only 23 bits wide) - --> $DIR/cast.rs:19:5 + --> $DIR/cast.rs:18:5 | LL | x3 as f32; | ^^^^^^^^^ error: casting u64 to f64 causes a loss of precision (u64 is 64 bits wide, but f64's mantissa is only 52 bits wide) - --> $DIR/cast.rs:20:5 + --> $DIR/cast.rs:19:5 | LL | x3 as f64; | ^^^^^^^^^ error: casting f32 to i32 may truncate the value - --> $DIR/cast.rs:22:5 + --> $DIR/cast.rs:21:5 | LL | 1f32 as i32; | ^^^^^^^^^^^ @@ -45,13 +45,13 @@ LL | 1f32 as i32; = note: `-D clippy::cast-possible-truncation` implied by `-D warnings` error: casting f32 to u32 may truncate the value - --> $DIR/cast.rs:23:5 + --> $DIR/cast.rs:22:5 | LL | 1f32 as u32; | ^^^^^^^^^^^ error: casting f32 to u32 may lose the sign of the value - --> $DIR/cast.rs:23:5 + --> $DIR/cast.rs:22:5 | LL | 1f32 as u32; | ^^^^^^^^^^^ @@ -59,43 +59,43 @@ LL | 1f32 as u32; = note: `-D clippy::cast-sign-loss` implied by `-D warnings` error: casting f64 to f32 may truncate the value - --> $DIR/cast.rs:24:5 + --> $DIR/cast.rs:23:5 | LL | 1f64 as f32; | ^^^^^^^^^^^ error: casting i32 to i8 may truncate the value - --> $DIR/cast.rs:25:5 + --> $DIR/cast.rs:24:5 | LL | 1i32 as i8; | ^^^^^^^^^^ error: casting i32 to u8 may truncate the value - --> $DIR/cast.rs:26:5 + --> $DIR/cast.rs:25:5 | LL | 1i32 as u8; | ^^^^^^^^^^ error: casting f64 to isize may truncate the value - --> $DIR/cast.rs:27:5 + --> $DIR/cast.rs:26:5 | LL | 1f64 as isize; | ^^^^^^^^^^^^^ error: casting f64 to usize may truncate the value - --> $DIR/cast.rs:28:5 + --> $DIR/cast.rs:27:5 | LL | 1f64 as usize; | ^^^^^^^^^^^^^ error: casting f64 to usize may lose the sign of the value - --> $DIR/cast.rs:28:5 + --> $DIR/cast.rs:27:5 | LL | 1f64 as usize; | ^^^^^^^^^^^^^ error: casting u8 to i8 may wrap around the value - --> $DIR/cast.rs:30:5 + --> $DIR/cast.rs:29:5 | LL | 1u8 as i8; | ^^^^^^^^^ @@ -103,57 +103,43 @@ LL | 1u8 as i8; = note: `-D clippy::cast-possible-wrap` implied by `-D warnings` error: casting u16 to i16 may wrap around the value - --> $DIR/cast.rs:31:5 + --> $DIR/cast.rs:30:5 | LL | 1u16 as i16; | ^^^^^^^^^^^ error: casting u32 to i32 may wrap around the value - --> $DIR/cast.rs:32:5 + --> $DIR/cast.rs:31:5 | LL | 1u32 as i32; | ^^^^^^^^^^^ error: casting u64 to i64 may wrap around the value - --> $DIR/cast.rs:33:5 + --> $DIR/cast.rs:32:5 | LL | 1u64 as i64; | ^^^^^^^^^^^ error: casting usize to isize may wrap around the value - --> $DIR/cast.rs:34:5 + --> $DIR/cast.rs:33:5 | LL | 1usize as isize; | ^^^^^^^^^^^^^^^ -error: casting f32 to f64 may become silently lossy if types change - --> $DIR/cast.rs:36:5 - | -LL | 1.0f32 as f64; - | ^^^^^^^^^^^^^ help: try: `f64::from(1.0f32)` - | - = note: `-D clippy::cast-lossless` implied by `-D warnings` - -error: casting u8 to u16 may become silently lossy if types change - --> $DIR/cast.rs:38:5 - | -LL | (1u8 + 1u8) as u16; - | ^^^^^^^^^^^^^^^^^^ help: try: `u16::from(1u8 + 1u8)` - error: casting i32 to u32 may lose the sign of the value - --> $DIR/cast.rs:41:5 + --> $DIR/cast.rs:36:5 | LL | -1i32 as u32; | ^^^^^^^^^^^^ error: casting isize to usize may lose the sign of the value - --> $DIR/cast.rs:43:5 + --> $DIR/cast.rs:38:5 | LL | -1isize as usize; | ^^^^^^^^^^^^^^^^ error: casting to the same type is unnecessary (`i32` -> `i32`) - --> $DIR/cast.rs:52:5 + --> $DIR/cast.rs:47:5 | LL | 1i32 as i32; | ^^^^^^^^^^^ @@ -161,34 +147,34 @@ LL | 1i32 as i32; = note: `-D clippy::unnecessary-cast` implied by `-D warnings` error: casting to the same type is unnecessary (`f32` -> `f32`) - --> $DIR/cast.rs:53:5 + --> $DIR/cast.rs:48:5 | LL | 1f32 as f32; | ^^^^^^^^^^^ error: casting to the same type is unnecessary (`bool` -> `bool`) - --> $DIR/cast.rs:54:5 + --> $DIR/cast.rs:49:5 | LL | false as bool; | ^^^^^^^^^^^^^ error: casting integer literal to f32 is unnecessary - --> $DIR/cast.rs:57:5 + --> $DIR/cast.rs:52:5 | LL | 100 as f32; | ^^^^^^^^^^ help: try: `100_f32` error: casting integer literal to f64 is unnecessary - --> $DIR/cast.rs:58:5 + --> $DIR/cast.rs:53:5 | LL | 100 as f64; | ^^^^^^^^^^ help: try: `100_f64` error: casting integer literal to f64 is unnecessary - --> $DIR/cast.rs:59:5 + --> $DIR/cast.rs:54:5 | LL | 100_i32 as f64; | ^^^^^^^^^^^^^^ help: try: `100_f64` -error: aborting due to 30 previous errors +error: aborting due to 28 previous errors diff --git a/tests/ui/cast_lossless_float.fixed b/tests/ui/cast_lossless_float.fixed index 4df0faf0b3e6..8021dc229e5e 100644 --- a/tests/ui/cast_lossless_float.fixed +++ b/tests/ui/cast_lossless_float.fixed @@ -21,6 +21,9 @@ fn main() { f64::from(x4); let x5 = 1u32; f64::from(x5); + + // Test with casts from floating-point types + f64::from(1.0f32); } // The lint would suggest using `f64::from(input)` here but the `XX::from` function is not const, diff --git a/tests/ui/cast_lossless_float.rs b/tests/ui/cast_lossless_float.rs index a8d5ed2508c7..3cd5ad622036 100644 --- a/tests/ui/cast_lossless_float.rs +++ b/tests/ui/cast_lossless_float.rs @@ -21,6 +21,9 @@ fn main() { x4 as f64; let x5 = 1u32; x5 as f64; + + // Test with casts from floating-point types + 1.0f32 as f64; } // The lint would suggest using `f64::from(input)` here but the `XX::from` function is not const, diff --git a/tests/ui/cast_lossless_float.stderr b/tests/ui/cast_lossless_float.stderr index 942c3d22bdcc..b57af31196ef 100644 --- a/tests/ui/cast_lossless_float.stderr +++ b/tests/ui/cast_lossless_float.stderr @@ -60,5 +60,11 @@ error: casting u32 to f64 may become silently lossy if types change LL | x5 as f64; | ^^^^^^^^^ help: try: `f64::from(x5)` -error: aborting due to 10 previous errors +error: casting f32 to f64 may become silently lossy if types change + --> $DIR/cast_lossless_float.rs:26:5 + | +LL | 1.0f32 as f64; + | ^^^^^^^^^^^^^ help: try: `f64::from(1.0f32)` + +error: aborting due to 11 previous errors diff --git a/tests/ui/cast_lossless_integer.fixed b/tests/ui/cast_lossless_integer.fixed index 6c384e7d38cf..22936e41c909 100644 --- a/tests/ui/cast_lossless_integer.fixed +++ b/tests/ui/cast_lossless_integer.fixed @@ -23,6 +23,9 @@ fn main() { i64::from(1i32); i64::from(1u32); u64::from(1u32); + + // Test with an expression wrapped in parens + u16::from(1u8 + 1u8); } // The lint would suggest using `f64::from(input)` here but the `XX::from` function is not const, diff --git a/tests/ui/cast_lossless_integer.rs b/tests/ui/cast_lossless_integer.rs index 35970bca88c8..958a336cf2cd 100644 --- a/tests/ui/cast_lossless_integer.rs +++ b/tests/ui/cast_lossless_integer.rs @@ -23,6 +23,9 @@ fn main() { 1i32 as i64; 1u32 as i64; 1u32 as u64; + + // Test with an expression wrapped in parens + (1u8 + 1u8) as u16; } // The lint would suggest using `f64::from(input)` here but the `XX::from` function is not const, diff --git a/tests/ui/cast_lossless_integer.stderr b/tests/ui/cast_lossless_integer.stderr index ff98ec84a148..1fe011f69336 100644 --- a/tests/ui/cast_lossless_integer.stderr +++ b/tests/ui/cast_lossless_integer.stderr @@ -108,5 +108,11 @@ error: casting u32 to u64 may become silently lossy if types change LL | 1u32 as u64; | ^^^^^^^^^^^ help: try: `u64::from(1u32)` -error: aborting due to 18 previous errors +error: casting u8 to u16 may become silently lossy if types change + --> $DIR/cast_lossless_integer.rs:28:5 + | +LL | (1u8 + 1u8) as u16; + | ^^^^^^^^^^^^^^^^^^ help: try: `u16::from(1u8 + 1u8)` + +error: aborting due to 19 previous errors diff --git a/tests/ui/cognitive_complexity.rs b/tests/ui/cognitive_complexity/legacy.rs similarity index 79% rename from tests/ui/cognitive_complexity.rs rename to tests/ui/cognitive_complexity/legacy.rs index 4e4016e78c2a..2f3c40c94661 100644 --- a/tests/ui/cognitive_complexity.rs +++ b/tests/ui/cognitive_complexity/legacy.rs @@ -2,90 +2,11 @@ #![warn(clippy::cognitive_complexity)] #![allow(unused)] -#[rustfmt::skip] -fn main() { - if true { - println!("a"); - } - if true { - println!("a"); - } - if true { - println!("a"); - } - if true { - println!("a"); - } - if true { - println!("a"); - } - if true { - println!("a"); - } - if true { - println!("a"); - } - if true { - println!("a"); - } - if true { - println!("a"); - } - if true { - println!("a"); - } - if true { - println!("a"); - } - if true { - println!("a"); - } - if true { - println!("a"); - } - if true { - println!("a"); - } - if true { - println!("a"); - } - if true { - println!("a"); - } - if true { - println!("a"); - } - if true { - println!("a"); - } - if true { - println!("a"); - } - if true { - println!("a"); - } - if true { - println!("a"); - } - if true { - println!("a"); - } - if true { - println!("a"); - } - if true { - println!("a"); - } - if true { - println!("a"); - } - if true { - println!("a"); - } - if true { - println!("a"); - } -} +fn main() {} + +/* + These tests must be reviewed and either eliminated or repurposed +*/ #[clippy::cognitive_complexity = "0"] fn kaboom() { @@ -133,16 +54,6 @@ fn bloo() { } } -#[clippy::cognitive_complexity = "0"] -fn lots_of_short_circuits() -> bool { - true && false && true && false && true && false && true -} - -#[clippy::cognitive_complexity = "0"] -fn lots_of_short_circuits2() -> bool { - true || false || true || false || true || false || true -} - #[clippy::cognitive_complexity = "0"] fn baa() { let x = || match 99 { @@ -169,17 +80,6 @@ fn bar() { } } -#[test] -#[clippy::cognitive_complexity = "0"] -/// Tests are usually complex but simple at the same time. `clippy::cognitive_complexity` used to -/// give lots of false-positives in tests. -fn dont_warn_on_tests() { - match 99 { - 0 => println!("hi"), - _ => println!("bye"), - } -} - #[clippy::cognitive_complexity = "0"] fn barr() { match 99 { @@ -369,3 +269,20 @@ fn early_ret() -> i32 { _ => return 6, } } + +#[clippy::cognitive_complexity = "0"] +fn osscilating_logical_chain_1() -> bool { + true && false || true && false +} + +// This tests that the only thing that matters +// is the change in operator +#[clippy::cognitive_complexity = "0"] +fn osscilating_logical_chain_2() -> bool { + true && false && true && false || true && false && true && false +} + +#[clippy::cognitive_complexity = "0"] +fn osscilating_logical_chain_3() -> bool { + (true && false) || (true && false) +} diff --git a/tests/ui/cognitive_complexity.stderr b/tests/ui/cognitive_complexity/legacy.stderr similarity index 64% rename from tests/ui/cognitive_complexity.stderr rename to tests/ui/cognitive_complexity/legacy.stderr index 168653b97116..714a7fca7860 100644 --- a/tests/ui/cognitive_complexity.stderr +++ b/tests/ui/cognitive_complexity/legacy.stderr @@ -1,20 +1,5 @@ -error: the function has a cognitive complexity of 28 - --> $DIR/cognitive_complexity.rs:6:1 - | -LL | / fn main() { -LL | | if true { -LL | | println!("a"); -LL | | } -... | -LL | | } -LL | | } - | |_^ - | - = note: `-D clippy::cognitive-complexity` implied by `-D warnings` - = help: you could split it up into multiple smaller functions - -error: the function has a cognitive complexity of 7 - --> $DIR/cognitive_complexity.rs:91:1 +error: the function has a cognitive complexity of 120 + --> $DIR/legacy.rs:12:1 | LL | / fn kaboom() { LL | | let n = 0; @@ -25,30 +10,11 @@ LL | | } LL | | } | |_^ | + = note: `-D clippy::cognitive-complexity` implied by `-D warnings` = help: you could split it up into multiple smaller functions -error: the function has a cognitive complexity of 1 - --> $DIR/cognitive_complexity.rs:137:1 - | -LL | / fn lots_of_short_circuits() -> bool { -LL | | true && false && true && false && true && false && true -LL | | } - | |_^ - | - = help: you could split it up into multiple smaller functions - -error: the function has a cognitive complexity of 1 - --> $DIR/cognitive_complexity.rs:142:1 - | -LL | / fn lots_of_short_circuits2() -> bool { -LL | | true || false || true || false || true || false || true -LL | | } - | |_^ - | - = help: you could split it up into multiple smaller functions - -error: the function has a cognitive complexity of 2 - --> $DIR/cognitive_complexity.rs:147:1 +error: the function has a cognitive complexity of 50 + --> $DIR/legacy.rs:58:1 | LL | / fn baa() { LL | | let x = || match 99 { @@ -61,23 +27,8 @@ LL | | } | = help: you could split it up into multiple smaller functions -error: the function has a cognitive complexity of 2 - --> $DIR/cognitive_complexity.rs:148:13 - | -LL | let x = || match 99 { - | _____________^ -LL | | 0 => 0, -LL | | 1 => 1, -LL | | 2 => 2, -... | -LL | | _ => 42, -LL | | }; - | |_____^ - | - = help: you could split it up into multiple smaller functions - -error: the function has a cognitive complexity of 2 - --> $DIR/cognitive_complexity.rs:165:1 +error: the function has a cognitive complexity of 30 + --> $DIR/legacy.rs:76:1 | LL | / fn bar() { LL | | match 99 { @@ -89,8 +40,8 @@ LL | | } | = help: you could split it up into multiple smaller functions -error: the function has a cognitive complexity of 2 - --> $DIR/cognitive_complexity.rs:184:1 +error: the function has a cognitive complexity of 50 + --> $DIR/legacy.rs:84:1 | LL | / fn barr() { LL | | match 99 { @@ -103,8 +54,8 @@ LL | | } | = help: you could split it up into multiple smaller functions -error: the function has a cognitive complexity of 3 - --> $DIR/cognitive_complexity.rs:194:1 +error: the function has a cognitive complexity of 100 + --> $DIR/legacy.rs:94:1 | LL | / fn barr2() { LL | | match 99 { @@ -117,8 +68,8 @@ LL | | } | = help: you could split it up into multiple smaller functions -error: the function has a cognitive complexity of 2 - --> $DIR/cognitive_complexity.rs:210:1 +error: the function has a cognitive complexity of 50 + --> $DIR/legacy.rs:110:1 | LL | / fn barrr() { LL | | match 99 { @@ -131,8 +82,8 @@ LL | | } | = help: you could split it up into multiple smaller functions -error: the function has a cognitive complexity of 3 - --> $DIR/cognitive_complexity.rs:220:1 +error: the function has a cognitive complexity of 100 + --> $DIR/legacy.rs:120:1 | LL | / fn barrr2() { LL | | match 99 { @@ -145,8 +96,8 @@ LL | | } | = help: you could split it up into multiple smaller functions -error: the function has a cognitive complexity of 2 - --> $DIR/cognitive_complexity.rs:236:1 +error: the function has a cognitive complexity of 50 + --> $DIR/legacy.rs:136:1 | LL | / fn barrrr() { LL | | match 99 { @@ -159,8 +110,8 @@ LL | | } | = help: you could split it up into multiple smaller functions -error: the function has a cognitive complexity of 3 - --> $DIR/cognitive_complexity.rs:246:1 +error: the function has a cognitive complexity of 100 + --> $DIR/legacy.rs:146:1 | LL | / fn barrrr2() { LL | | match 99 { @@ -173,8 +124,8 @@ LL | | } | = help: you could split it up into multiple smaller functions -error: the function has a cognitive complexity of 2 - --> $DIR/cognitive_complexity.rs:262:1 +error: the function has a cognitive complexity of 40 + --> $DIR/legacy.rs:162:1 | LL | / fn cake() { LL | | if 4 == 5 { @@ -187,8 +138,8 @@ LL | | } | = help: you could split it up into multiple smaller functions -error: the function has a cognitive complexity of 4 - --> $DIR/cognitive_complexity.rs:272:1 +error: the function has a cognitive complexity of 110 + --> $DIR/legacy.rs:172:1 | LL | / pub fn read_file(input_path: &str) -> String { LL | | use std::fs::File; @@ -201,8 +152,8 @@ LL | | } | = help: you could split it up into multiple smaller functions -error: the function has a cognitive complexity of 1 - --> $DIR/cognitive_complexity.rs:303:1 +error: the function has a cognitive complexity of 20 + --> $DIR/legacy.rs:203:1 | LL | / fn void(void: Void) { LL | | if true { @@ -213,8 +164,19 @@ LL | | } | = help: you could split it up into multiple smaller functions -error: the function has a cognitive complexity of 1 - --> $DIR/cognitive_complexity.rs:316:1 +error: the function has a cognitive complexity of 20 + --> $DIR/legacy.rs:210:1 + | +LL | / fn mcarton_sees_all() { +LL | | panic!("meh"); +LL | | panic!("möh"); +LL | | } + | |_^ + | + = help: you could split it up into multiple smaller functions + +error: the function has a cognitive complexity of 30 + --> $DIR/legacy.rs:216:1 | LL | / fn try() -> Result { LL | | match 5 { @@ -226,8 +188,8 @@ LL | | } | = help: you could split it up into multiple smaller functions -error: the function has a cognitive complexity of 1 - --> $DIR/cognitive_complexity.rs:324:1 +error: the function has a cognitive complexity of 110 + --> $DIR/legacy.rs:224:1 | LL | / fn try_again() -> Result { LL | | let _ = try!(Ok(42)); @@ -240,8 +202,8 @@ LL | | } | = help: you could split it up into multiple smaller functions -error: the function has a cognitive complexity of 1 - --> $DIR/cognitive_complexity.rs:340:1 +error: the function has a cognitive complexity of 90 + --> $DIR/legacy.rs:240:1 | LL | / fn early() -> Result { LL | | return Ok(5); @@ -254,8 +216,8 @@ LL | | } | = help: you could split it up into multiple smaller functions -error: the function has a cognitive complexity of 8 - --> $DIR/cognitive_complexity.rs:354:1 +error: the function has a cognitive complexity of 130 + --> $DIR/legacy.rs:254:1 | LL | / fn early_ret() -> i32 { LL | | let a = if true { 42 } else { return 0; }; @@ -268,5 +230,35 @@ LL | | } | = help: you could split it up into multiple smaller functions +error: the function has a cognitive complexity of 30 + --> $DIR/legacy.rs:274:1 + | +LL | / fn osscilating_logical_chain_1() -> bool { +LL | | true && false || true && false +LL | | } + | |_^ + | + = help: you could split it up into multiple smaller functions + +error: the function has a cognitive complexity of 30 + --> $DIR/legacy.rs:281:1 + | +LL | / fn osscilating_logical_chain_2() -> bool { +LL | | true && false && true && false || true && false && true && false +LL | | } + | |_^ + | + = help: you could split it up into multiple smaller functions + +error: the function has a cognitive complexity of 30 + --> $DIR/legacy.rs:286:1 + | +LL | / fn osscilating_logical_chain_3() -> bool { +LL | | (true && false) || (true && false) +LL | | } + | |_^ + | + = help: you could split it up into multiple smaller functions + error: aborting due to 20 previous errors diff --git a/tests/ui/cognitive_complexity/nd_structures.rs b/tests/ui/cognitive_complexity/nd_structures.rs new file mode 100644 index 000000000000..93bc6133e0fb --- /dev/null +++ b/tests/ui/cognitive_complexity/nd_structures.rs @@ -0,0 +1,5 @@ +#![allow(clippy::all)] +#![warn(clippy::cognitive_complexity)] +#![allow(unused)] + +fn main() {} diff --git a/tests/ui/cognitive_complexity/nd_structures.stderr b/tests/ui/cognitive_complexity/nd_structures.stderr new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/tests/ui/cognitive_complexity/ni_structures.rs b/tests/ui/cognitive_complexity/ni_structures.rs new file mode 100644 index 000000000000..bb8bba95b1ef --- /dev/null +++ b/tests/ui/cognitive_complexity/ni_structures.rs @@ -0,0 +1,197 @@ +#![allow(clippy::all)] +#![warn(clippy::cognitive_complexity)] +#![allow(unused)] + +fn main() {} + +/* + Tests for Nesting-Independent Structures +*/ + +#[clippy::cognitive_complexity = "0"] +fn func_calls() { + let _ = Vec::new(); +} + +#[clippy::cognitive_complexity = "0"] +fn macro_calls() { + println!("Hello!"); +} + +mod loop_change_statements { + + /* + ### We check that their most basic form scores 1 ### + */ + + #[clippy::cognitive_complexity = "1"] + fn b_reak() { + loop { + break; + } + } + + #[clippy::cognitive_complexity = "1"] + fn c_ontinue() { + loop { + continue; + } + } + + #[clippy::cognitive_complexity = "2"] + fn break_plus_ni_expr() -> bool { + loop { + break { + true || false + } + } + } + + #[clippy::cognitive_complexity = "3"] + fn break_plus_nd_expr() -> bool { + loop { + break { + if(true) { + println!("Hello"); + } + } + } + } +} + +mod binary_logic { + + /* + ### The base cases should score 1 ### + */ + + #[clippy::cognitive_complexity = "0"] + fn and(a: bool, b: bool) -> bool { + a && b + } + + #[clippy::cognitive_complexity = "0"] + fn or(a: bool, b: bool) -> bool { + a || b + } + + #[clippy::cognitive_complexity = "0"] + fn bit_and(a: bool, b: bool) -> bool { + a & b + } + + #[clippy::cognitive_complexity = "0"] + fn bit_or(a: bool, b: bool) -> bool { + a | b + } + + #[clippy::cognitive_complexity = "0"] + fn bit_xor(a: bool, b: bool) -> bool { + a ^ b + } + + /* + ### All of these should score 2 ### + */ + + #[clippy::cognitive_complexity = "1"] + fn change_one_1(a: bool, b: bool, c: bool) -> bool { + a && b || c + } + + #[clippy::cognitive_complexity = "1"] + fn change_one_2(a: bool, b: bool, c: bool) -> bool { + a && b & c + } + + #[clippy::cognitive_complexity = "1"] + fn change_one_3(a: bool, b: bool, c: bool) -> bool { + a && b | c + } + + #[clippy::cognitive_complexity = "1"] + fn change_one_4(a: bool, b: bool, c: bool) -> bool { + a && b ^ c + } + + #[clippy::cognitive_complexity = "1"] + fn change_one_5(a: bool, b: bool, c: bool) -> bool { + a || b & c + } + + #[clippy::cognitive_complexity = "1"] + fn change_one_6(a: bool, b: bool, c: bool) -> bool { + a || b | c + } + + #[clippy::cognitive_complexity = "1"] + fn change_one_7(a: bool, b: bool, c: bool) -> bool { + a || b ^ c + } + + #[clippy::cognitive_complexity = "1"] + fn change_one_8(a: bool, b: bool, c: bool) -> bool { + a & b | c + } + + #[clippy::cognitive_complexity = "1"] + fn change_one_9(a: bool, b: bool, c: bool) -> bool { + a & b ^ c + } + + #[clippy::cognitive_complexity = "1"] + fn change_one_10(a: bool, b: bool, c: bool) -> bool { + a | b ^ c + } + + /* + ### These should score 2 as well ### + */ + + #[clippy::cognitive_complexity = "1"] + fn one_paren(a: bool, b: bool, c: bool) -> bool { + a && (b || c) + } + + #[clippy::cognitive_complexity = "1"] + fn two_paren(a: bool, b: bool, c: bool) -> bool { + a & ((b | c)) + } + + #[clippy::cognitive_complexity = "1"] + fn one_unary(a: bool, b: bool, c: bool) -> bool { + a ^ b && !c + } + + #[clippy::cognitive_complexity = "1"] + fn one_unary_one_paren(a: bool, b: bool, c: bool) -> bool { + a || !(b & c) + } + + mod complex_patterns { + + /* + These patterns are made to test that the + binary logic scoring algorithm recurses correctly + */ + + #[clippy::cognitive_complexity = "3"] + fn right_side_is_a_trap_1(a: bool, b: bool, c: bool, d: bool, e: bool) -> bool { + // Here, if the algorithm recurses to the right instead of the left, + // it should produce a lower score. + (a && b) || ((c ^ d) || e) + } + + #[clippy::cognitive_complexity = "3"] + fn right_side_is_a_trap_2(a: bool, b: bool, c: bool, d: bool, e: bool) -> bool { + // Same as (right_side_is_a_trap_1), this tries to check that + // the algorithm's direction is correct + (a && b) || (((c ^ d) || e) || c) + } + + #[clippy::cognitive_complexity = "0"] + fn super_long_chain(a: bool, b: bool, c: bool, d: bool, e: bool) -> bool { + a && b && c && d && e + } + } +} diff --git a/tests/ui/cognitive_complexity/ni_structures.stderr b/tests/ui/cognitive_complexity/ni_structures.stderr new file mode 100644 index 000000000000..1438b4f36f15 --- /dev/null +++ b/tests/ui/cognitive_complexity/ni_structures.stderr @@ -0,0 +1,312 @@ +error: the function has a cognitive complexity of 10 + --> $DIR/ni_structures.rs:12:1 + | +LL | / fn func_calls() { +LL | | let _ = Vec::new(); +LL | | } + | |_^ + | + = note: `-D clippy::cognitive-complexity` implied by `-D warnings` + = help: you could split it up into multiple smaller functions + +error: the function has a cognitive complexity of 10 + --> $DIR/ni_structures.rs:17:1 + | +LL | / fn macro_calls() { +LL | | println!("Hello!"); +LL | | } + | |_^ + | + = help: you could split it up into multiple smaller functions + +error: the function has a cognitive complexity of 20 + --> $DIR/ni_structures.rs:28:5 + | +LL | / fn b_reak() { +LL | | loop { +LL | | break; +LL | | } +LL | | } + | |_____^ + | + = help: you could split it up into multiple smaller functions + +error: the function has a cognitive complexity of 20 + --> $DIR/ni_structures.rs:35:5 + | +LL | / fn c_ontinue() { +LL | | loop { +LL | | continue; +LL | | } +LL | | } + | |_____^ + | + = help: you could split it up into multiple smaller functions + +error: the function has a cognitive complexity of 30 + --> $DIR/ni_structures.rs:42:5 + | +LL | / fn break_plus_ni_expr() -> bool { +LL | | loop { +LL | | break { +LL | | true || false +LL | | } +LL | | } +LL | | } + | |_____^ + | + = help: you could split it up into multiple smaller functions + +error: the function has a cognitive complexity of 40 + --> $DIR/ni_structures.rs:51:5 + | +LL | / fn break_plus_nd_expr() -> bool { +LL | | loop { +LL | | break { +LL | | if(true) { +... | +LL | | } +LL | | } + | |_____^ + | + = help: you could split it up into multiple smaller functions + +error: the function has a cognitive complexity of 10 + --> $DIR/ni_structures.rs:69:5 + | +LL | / fn and(a: bool, b: bool) -> bool { +LL | | a && b +LL | | } + | |_____^ + | + = help: you could split it up into multiple smaller functions + +error: the function has a cognitive complexity of 10 + --> $DIR/ni_structures.rs:74:5 + | +LL | / fn or(a: bool, b: bool) -> bool { +LL | | a || b +LL | | } + | |_____^ + | + = help: you could split it up into multiple smaller functions + +error: the function has a cognitive complexity of 10 + --> $DIR/ni_structures.rs:79:5 + | +LL | / fn bit_and(a: bool, b: bool) -> bool { +LL | | a & b +LL | | } + | |_____^ + | + = help: you could split it up into multiple smaller functions + +error: the function has a cognitive complexity of 10 + --> $DIR/ni_structures.rs:84:5 + | +LL | / fn bit_or(a: bool, b: bool) -> bool { +LL | | a | b +LL | | } + | |_____^ + | + = help: you could split it up into multiple smaller functions + +error: the function has a cognitive complexity of 10 + --> $DIR/ni_structures.rs:89:5 + | +LL | / fn bit_xor(a: bool, b: bool) -> bool { +LL | | a ^ b +LL | | } + | |_____^ + | + = help: you could split it up into multiple smaller functions + +error: the function has a cognitive complexity of 20 + --> $DIR/ni_structures.rs:98:5 + | +LL | / fn change_one_1(a: bool, b: bool, c: bool) -> bool { +LL | | a && b || c +LL | | } + | |_____^ + | + = help: you could split it up into multiple smaller functions + +error: the function has a cognitive complexity of 20 + --> $DIR/ni_structures.rs:103:5 + | +LL | / fn change_one_2(a: bool, b: bool, c: bool) -> bool { +LL | | a && b & c +LL | | } + | |_____^ + | + = help: you could split it up into multiple smaller functions + +error: the function has a cognitive complexity of 20 + --> $DIR/ni_structures.rs:108:5 + | +LL | / fn change_one_3(a: bool, b: bool, c: bool) -> bool { +LL | | a && b | c +LL | | } + | |_____^ + | + = help: you could split it up into multiple smaller functions + +error: the function has a cognitive complexity of 20 + --> $DIR/ni_structures.rs:113:5 + | +LL | / fn change_one_4(a: bool, b: bool, c: bool) -> bool { +LL | | a && b ^ c +LL | | } + | |_____^ + | + = help: you could split it up into multiple smaller functions + +error: the function has a cognitive complexity of 20 + --> $DIR/ni_structures.rs:118:5 + | +LL | / fn change_one_5(a: bool, b: bool, c: bool) -> bool { +LL | | a || b & c +LL | | } + | |_____^ + | + = help: you could split it up into multiple smaller functions + +error: the function has a cognitive complexity of 20 + --> $DIR/ni_structures.rs:123:5 + | +LL | / fn change_one_6(a: bool, b: bool, c: bool) -> bool { +LL | | a || b | c +LL | | } + | |_____^ + | + = help: you could split it up into multiple smaller functions + +error: the function has a cognitive complexity of 20 + --> $DIR/ni_structures.rs:128:5 + | +LL | / fn change_one_7(a: bool, b: bool, c: bool) -> bool { +LL | | a || b ^ c +LL | | } + | |_____^ + | + = help: you could split it up into multiple smaller functions + +error: the function has a cognitive complexity of 20 + --> $DIR/ni_structures.rs:133:5 + | +LL | / fn change_one_8(a: bool, b: bool, c: bool) -> bool { +LL | | a & b | c +LL | | } + | |_____^ + | + = help: you could split it up into multiple smaller functions + +error: the function has a cognitive complexity of 20 + --> $DIR/ni_structures.rs:138:5 + | +LL | / fn change_one_9(a: bool, b: bool, c: bool) -> bool { +LL | | a & b ^ c +LL | | } + | |_____^ + | + = help: you could split it up into multiple smaller functions + +error: the function has a cognitive complexity of 20 + --> $DIR/ni_structures.rs:143:5 + | +LL | / fn change_one_10(a: bool, b: bool, c: bool) -> bool { +LL | | a | b ^ c +LL | | } + | |_____^ + | + = help: you could split it up into multiple smaller functions + +error: the function has a cognitive complexity of 20 + --> $DIR/ni_structures.rs:152:5 + | +LL | / fn one_paren(a: bool, b: bool, c: bool) -> bool { +LL | | a && (b || c) +LL | | } + | |_____^ + | + = help: you could split it up into multiple smaller functions + +error: the function has a cognitive complexity of 20 + --> $DIR/ni_structures.rs:157:5 + | +LL | / fn two_paren(a: bool, b: bool, c: bool) -> bool { +LL | | a & ((b | c)) +LL | | } + | |_____^ + | + = help: you could split it up into multiple smaller functions + +error: the function has a cognitive complexity of 20 + --> $DIR/ni_structures.rs:162:5 + | +LL | / fn one_unary(a: bool, b: bool, c: bool) -> bool { +LL | | a ^ b && !c +LL | | } + | |_____^ + | + = help: you could split it up into multiple smaller functions + +error: the function has a cognitive complexity of 20 + --> $DIR/ni_structures.rs:167:5 + | +LL | / fn one_unary_one_paren(a: bool, b: bool, c: bool) -> bool { +LL | | a || !(b & c) +LL | | } + | |_____^ + | + = help: you could split it up into multiple smaller functions + +error: the function has a cognitive complexity of 40 + --> $DIR/ni_structures.rs:179:9 + | +LL | / fn right_side_is_a_trap_1(a: bool, b: bool, c: bool, d: bool, e: bool) -> bool { +LL | | // Here, if the algorithm recurses to the right instead of the left, +LL | | // it should produce a lower score. +LL | | (a && b) || ((c ^ d) || e) +LL | | } + | |_________^ + | + = help: you could split it up into multiple smaller functions + +error: the function has a cognitive complexity of 40 + --> $DIR/ni_structures.rs:186:9 + | +LL | / fn right_side_is_a_trap_2(a: bool, b: bool, c: bool, d: bool, e: bool) -> bool { +LL | | // Same as (right_side_is_a_trap_1), this tries to check that +LL | | // the algorithm's direction is correct +LL | | (a && b) || (((c ^ d) || e) || c) +LL | | } + | |_________^ + | + = help: you could split it up into multiple smaller functions + +error: the function has a cognitive complexity of 10 + --> $DIR/ni_structures.rs:193:9 + | +LL | / fn super_long_chain(a: bool, b: bool, c: bool, d: bool, e: bool) -> bool { +LL | | a && b && c && d && e +LL | | } + | |_________^ + | + = help: you could split it up into multiple smaller functions + +error[E0308]: mismatched types + --> $DIR/ni_structures.rs:54:26 + | +LL | if(true) { + | __________________________^ +LL | | println!("Hello"); +LL | | } + | |_________________^ expected bool, found () + | + = note: expected type `bool` + found type `()` + +error: aborting due to 29 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/cognitive_complexity/no_ops.rs b/tests/ui/cognitive_complexity/no_ops.rs new file mode 100644 index 000000000000..20c36b54b8ba --- /dev/null +++ b/tests/ui/cognitive_complexity/no_ops.rs @@ -0,0 +1,71 @@ +#![allow(clippy::all)] +#![warn(clippy::cognitive_complexity)] +#![allow(unused)] + +fn main() {} + +/* + A collection of functions that should + mark no score. +*/ + +#[clippy::cognitive_complexity = "1"] +fn chaining_with_one_block(a: bool, b: bool, c: bool) -> bool { + a ^ {b && c} +} + +/* + Tests should never be scored +*/ + +// This is a normal test function + +#[test] +#[clippy::cognitive_complexity = "0"] +fn simple_test(n: usize) { + for i in range(0, n) { + for j in range(0, n) { + println!("{}, {}", i, j); + } + } +} + +// This is a test function with an inner function. +// None should be scored + +#[test] +#[clippy::cognitive_complexity = "0"] +fn test_with_inner_function(n: usize) { + fn print_and_exaggerate(n: usize) { + println!("{}000", n); + } + + for i in range(0, n) { + print_and_exaggerate(n); + } +} + +/* + Macros should not be expanded +*/ + +macro_rules! lucas_macro { + ($n: expr) => { + { + fn lucas_number(n: usize) -> usize { + match n { + 0 => 2, + 1 => 1, + _ => lucas_number(n - 1) + lucas_number(n - 2), + } + } + + lucas_number($n) + } + } +} + +#[clippy::cognitive_complexity = "1"] +fn macros_are_not_expanded(n: usize) -> usize { + lucas_macro!(n) +} diff --git a/tests/ui/cognitive_complexity/no_ops.stderr b/tests/ui/cognitive_complexity/no_ops.stderr new file mode 100644 index 000000000000..1bd361bcad22 --- /dev/null +++ b/tests/ui/cognitive_complexity/no_ops.stderr @@ -0,0 +1,23 @@ +error: the function has a cognitive complexity of 10 + --> $DIR/no_ops.rs:13:1 + | +LL | / fn chaining_with_one_block(a: bool, b: bool, c: bool) -> bool { +LL | | a ^ {b && c} +LL | | } + | |_^ + | + = note: `-D clippy::cognitive-complexity` implied by `-D warnings` + = help: you could split it up into multiple smaller functions + +error: the function has a cognitive complexity of 10 + --> $DIR/no_ops.rs:69:1 + | +LL | / fn macros_are_not_expanded(n: usize) -> usize { +LL | | lucas_macro!(n) +LL | | } + | |_^ + | + = help: you could split it up into multiple smaller functions + +error: aborting due to 2 previous errors + diff --git a/tests/ui/cognitive_complexity/other_cases.rs b/tests/ui/cognitive_complexity/other_cases.rs new file mode 100644 index 000000000000..087258266bda --- /dev/null +++ b/tests/ui/cognitive_complexity/other_cases.rs @@ -0,0 +1,21 @@ +#![allow(clippy::all)] +#![warn(clippy::cognitive_complexity)] +#![allow(unused)] + +fn main() {} + +/* + Other Tests +*/ + +#[clippy::cognitive_complexity = "1"] +fn nested_functions_are_counted(n: usize) -> usize { + fn lucas_number(n: usize) -> usize { + match n { + 0 => 2, + 1 => 1, + _ => lucas_number(n - 1) + lucas_number(n - 2), + } + } + lucas_number(n) +} diff --git a/tests/ui/cognitive_complexity/other_cases.stderr b/tests/ui/cognitive_complexity/other_cases.stderr new file mode 100644 index 000000000000..28cecc7957e4 --- /dev/null +++ b/tests/ui/cognitive_complexity/other_cases.stderr @@ -0,0 +1,17 @@ +error: the function has a cognitive complexity of 40 + --> $DIR/other_cases.rs:12:1 + | +LL | / fn nested_functions_are_counted(n: usize) -> usize { +LL | | fn lucas_number(n: usize) -> usize { +LL | | match n { +LL | | 0 => 2, +... | +LL | | lucas_number(n) +LL | | } + | |_^ + | + = note: `-D clippy::cognitive-complexity` implied by `-D warnings` + = help: you could split it up into multiple smaller functions + +error: aborting due to previous error + diff --git a/tests/ui/cognitive_complexity/too_complex_by_default.rs b/tests/ui/cognitive_complexity/too_complex_by_default.rs new file mode 100644 index 000000000000..0275ae45d566 --- /dev/null +++ b/tests/ui/cognitive_complexity/too_complex_by_default.rs @@ -0,0 +1,9 @@ +#![allow(clippy::all)] +#![warn(clippy::cognitive_complexity)] +#![allow(unused)] + +fn main() {} + +/* + Tests that trigger the default CoC value. +*/ diff --git a/tests/ui/cognitive_complexity_attr_used.rs b/tests/ui/cognitive_complexity_attr_used.rs deleted file mode 100644 index 403eff566ed6..000000000000 --- a/tests/ui/cognitive_complexity_attr_used.rs +++ /dev/null @@ -1,15 +0,0 @@ -#![warn(clippy::cognitive_complexity)] -#![warn(unused)] - -fn main() { - kaboom(); -} - -#[clippy::cognitive_complexity = "0"] -fn kaboom() { - if 42 == 43 { - panic!(); - } else if "cake" == "lie" { - println!("what?"); - } -} diff --git a/tests/ui/cognitive_complexity_attr_used.stderr b/tests/ui/cognitive_complexity_attr_used.stderr deleted file mode 100644 index 2cf41506f566..000000000000 --- a/tests/ui/cognitive_complexity_attr_used.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error: the function has a cognitive complexity of 3 - --> $DIR/cognitive_complexity_attr_used.rs:9:1 - | -LL | / fn kaboom() { -LL | | if 42 == 43 { -LL | | panic!(); -LL | | } else if "cake" == "lie" { -LL | | println!("what?"); -LL | | } -LL | | } - | |_^ - | - = note: `-D clippy::cognitive-complexity` implied by `-D warnings` - = help: you could split it up into multiple smaller functions - -error: aborting due to previous error - diff --git a/tests/ui/deref_addrof.fixed b/tests/ui/deref_addrof.fixed new file mode 100644 index 000000000000..9e5b51d6d5e6 --- /dev/null +++ b/tests/ui/deref_addrof.fixed @@ -0,0 +1,39 @@ +// run-rustfix + +fn get_number() -> usize { + 10 +} + +fn get_reference(n: &usize) -> &usize { + n +} + +#[allow(clippy::many_single_char_names, clippy::double_parens)] +#[allow(unused_variables, unused_parens)] +#[warn(clippy::deref_addrof)] +fn main() { + let a = 10; + let aref = &a; + + let b = a; + + let b = get_number(); + + let b = *get_reference(&a); + + let bytes: Vec = vec![1, 2, 3, 4]; + let b = bytes[1..2][0]; + + //This produces a suggestion of 'let b = (a);' which + //will trigger the 'unused_parens' lint + let b = (a); + + let b = a; + + #[rustfmt::skip] + let b = a; + + let b = &a; + + let b = *aref; +} diff --git a/tests/ui/reference.rs b/tests/ui/deref_addrof.rs similarity index 59% rename from tests/ui/reference.rs rename to tests/ui/deref_addrof.rs index c63997fa8583..5641a73cbc1c 100644 --- a/tests/ui/reference.rs +++ b/tests/ui/deref_addrof.rs @@ -1,3 +1,5 @@ +// run-rustfix + fn get_number() -> usize { 10 } @@ -7,7 +9,7 @@ fn get_reference(n: &usize) -> &usize { } #[allow(clippy::many_single_char_names, clippy::double_parens)] -#[allow(unused_variables)] +#[allow(unused_variables, unused_parens)] #[warn(clippy::deref_addrof)] fn main() { let a = 10; @@ -34,20 +36,4 @@ fn main() { let b = *&&a; let b = **&aref; - - //This produces a suggestion of 'let b = *&a;' which - //will trigger the 'clippy::deref_addrof' lint again - let b = **&&a; - - { - let mut x = 10; - let y = *&mut x; - } - - { - //This produces a suggestion of 'let y = *&mut x' which - //will trigger the 'clippy::deref_addrof' lint again - let mut x = 10; - let y = **&mut &mut x; - } } diff --git a/tests/ui/reference.stderr b/tests/ui/deref_addrof.stderr similarity index 58% rename from tests/ui/reference.stderr rename to tests/ui/deref_addrof.stderr index aea95a7fa9f3..bc51719e8a7a 100644 --- a/tests/ui/reference.stderr +++ b/tests/ui/deref_addrof.stderr @@ -1,5 +1,5 @@ error: immediately dereferencing a reference - --> $DIR/reference.rs:16:13 + --> $DIR/deref_addrof.rs:18:13 | LL | let b = *&a; | ^^^ help: try this: `a` @@ -7,64 +7,46 @@ LL | let b = *&a; = note: `-D clippy::deref-addrof` implied by `-D warnings` error: immediately dereferencing a reference - --> $DIR/reference.rs:18:13 + --> $DIR/deref_addrof.rs:20:13 | LL | let b = *&get_number(); | ^^^^^^^^^^^^^^ help: try this: `get_number()` error: immediately dereferencing a reference - --> $DIR/reference.rs:23:13 + --> $DIR/deref_addrof.rs:25:13 | LL | let b = *&bytes[1..2][0]; | ^^^^^^^^^^^^^^^^ help: try this: `bytes[1..2][0]` error: immediately dereferencing a reference - --> $DIR/reference.rs:27:13 + --> $DIR/deref_addrof.rs:29:13 | LL | let b = *&(a); | ^^^^^ help: try this: `(a)` error: immediately dereferencing a reference - --> $DIR/reference.rs:29:13 + --> $DIR/deref_addrof.rs:31:13 | LL | let b = *(&a); | ^^^^^ help: try this: `a` error: immediately dereferencing a reference - --> $DIR/reference.rs:32:13 + --> $DIR/deref_addrof.rs:34:13 | LL | let b = *((&a)); | ^^^^^^^ help: try this: `a` error: immediately dereferencing a reference - --> $DIR/reference.rs:34:13 + --> $DIR/deref_addrof.rs:36:13 | LL | let b = *&&a; | ^^^^ help: try this: `&a` error: immediately dereferencing a reference - --> $DIR/reference.rs:36:14 + --> $DIR/deref_addrof.rs:38:14 | LL | let b = **&aref; | ^^^^^^ help: try this: `aref` -error: immediately dereferencing a reference - --> $DIR/reference.rs:40:14 - | -LL | let b = **&&a; - | ^^^^ help: try this: `&a` - -error: immediately dereferencing a reference - --> $DIR/reference.rs:44:17 - | -LL | let y = *&mut x; - | ^^^^^^^ help: try this: `x` - -error: immediately dereferencing a reference - --> $DIR/reference.rs:51:18 - | -LL | let y = **&mut &mut x; - | ^^^^^^^^^^^^ help: try this: `&mut x` - -error: aborting due to 11 previous errors +error: aborting due to 8 previous errors diff --git a/tests/ui/deref_addrof_double_trigger.rs b/tests/ui/deref_addrof_double_trigger.rs new file mode 100644 index 000000000000..e19af5b9087f --- /dev/null +++ b/tests/ui/deref_addrof_double_trigger.rs @@ -0,0 +1,21 @@ +#[warn(clippy::deref_addrof)] +#[allow(unused_variables)] +fn main() { + let a = 10; + + //This produces a suggestion of 'let b = *&a;' which + //will trigger the 'clippy::deref_addrof' lint again + let b = **&&a; + + { + let mut x = 10; + let y = *&mut x; + } + + { + //This produces a suggestion of 'let y = *&mut x' which + //will trigger the 'clippy::deref_addrof' lint again + let mut x = 10; + let y = **&mut &mut x; + } +} diff --git a/tests/ui/deref_addrof_double_trigger.stderr b/tests/ui/deref_addrof_double_trigger.stderr new file mode 100644 index 000000000000..89284e1a8ed6 --- /dev/null +++ b/tests/ui/deref_addrof_double_trigger.stderr @@ -0,0 +1,22 @@ +error: immediately dereferencing a reference + --> $DIR/deref_addrof_double_trigger.rs:8:14 + | +LL | let b = **&&a; + | ^^^^ help: try this: `&a` + | + = note: `-D clippy::deref-addrof` implied by `-D warnings` + +error: immediately dereferencing a reference + --> $DIR/deref_addrof_double_trigger.rs:12:17 + | +LL | let y = *&mut x; + | ^^^^^^^ help: try this: `x` + +error: immediately dereferencing a reference + --> $DIR/deref_addrof_double_trigger.rs:19:18 + | +LL | let y = **&mut &mut x; + | ^^^^^^^^^^^^ help: try this: `&mut x` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/eta.fixed b/tests/ui/eta.fixed index 7e487fe21679..881d27efa798 100644 --- a/tests/ui/eta.fixed +++ b/tests/ui/eta.fixed @@ -7,8 +7,8 @@ clippy::many_single_char_names, clippy::needless_pass_by_value, clippy::option_map_unit_fn, - clippy::trivially_copy_pass_by_ref -)] + clippy::trivially_copy_pass_by_ref, + )] #![warn(clippy::redundant_closure, clippy::needless_borrow)] use std::path::PathBuf; @@ -67,37 +67,57 @@ impl<'a> std::ops::Deref for TestStruct<'a> { } fn test_redundant_closures_containing_method_calls() { - let i = 10; - let e = Some(TestStruct { some_ref: &i }).map(TestStruct::foo); - let e = Some(TestStruct { some_ref: &i }).map(TestStruct::foo); - let e = Some(TestStruct { some_ref: &i }).map(TestTrait::trait_foo); - let e = Some(TestStruct { some_ref: &i }).map(|a| a.trait_foo_ref()); - let e = Some(TestStruct { some_ref: &i }).map(TestTrait::trait_foo); - let e = Some(&mut vec![1, 2, 3]).map(std::vec::Vec::clear); - let e = Some(&mut vec![1, 2, 3]).map(std::vec::Vec::clear); - unsafe { - let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo_unsafe()); + + // In TestStruct use cases + { + let i = 10; + let _ = Some(TestStruct { some_ref: &i }).map(TestStruct::foo); + let _ = Some(TestStruct { some_ref: &i }).map(TestStruct::foo); + let _ = Some(TestStruct { some_ref: &i }).map(TestTrait::trait_foo); + let _ = Some(TestStruct { some_ref: &i }).map(|a| a.trait_foo_ref()); + let _ = Some(TestStruct { some_ref: &i }).map(TestTrait::trait_foo); + let _ = Some(TestStruct { some_ref: &i }) + .as_ref() + .map(|c| c.to_ascii_uppercase()); + unsafe { + let _ = Some(TestStruct { some_ref: &i }).map(|a| a.foo_unsafe()); + } } - let e = Some("str").map(std::string::ToString::to_string); - let e = Some("str").map(str::to_string); - let e = Some('a').map(char::to_uppercase); - let e = Some('a').map(char::to_uppercase); - let e: std::vec::Vec = vec!['a', 'b', 'c'].iter().map(|c| c.len_utf8()).collect(); - let e: std::vec::Vec = vec!['a', 'b', 'c'].iter().map(char::to_ascii_uppercase).collect(); - let e: std::vec::Vec = vec!['a', 'b', 'c'].iter().map(char::to_ascii_uppercase).collect(); - let p = Some(PathBuf::new()); - let e = p.as_ref().and_then(|s| s.to_str()); - let c = Some(TestStruct { some_ref: &i }) - .as_ref() - .map(|c| c.to_ascii_uppercase()); + // In a function that uses TestTrait fn test_different_borrow_levels(t: &[&T]) - where - T: TestTrait, + where T: TestTrait, { t.iter().filter(|x| x.trait_foo_ref()); t.iter().map(|x| x.trait_foo_ref()); } + + // In Vector operations + { + let _ = Some(&mut vec![1, 2, 3]).map(std::vec::Vec::clear); + let _ = Some(&mut vec![1, 2, 3]).map(std::vec::Vec::clear); + } + + // In String and Char operations + { + let _ = Some("str").map(std::string::ToString::to_string); + let _ = Some("str").map(str::to_string); + let _ = Some('a').map(char::to_uppercase); + let _ = Some('a').map(char::to_uppercase); + } + + // In Iterator Maps + { + let _: std::vec::Vec = vec!['a', 'b', 'c'].iter().map(|c| c.len_utf8()).collect(); + let _: std::vec::Vec = vec!['a', 'b', 'c'].iter().map(char::to_ascii_uppercase).collect(); + let _: std::vec::Vec = vec!['a', 'b', 'c'].iter().map(char::to_ascii_uppercase).collect(); + } + + // In other Cases + { + let p = Some(PathBuf::new()); + let _ = p.as_ref().and_then(|s| s.to_str()); + } } fn meta(f: F) diff --git a/tests/ui/eta.rs b/tests/ui/eta.rs index a0d83c438251..4e596bf8fe60 100644 --- a/tests/ui/eta.rs +++ b/tests/ui/eta.rs @@ -7,8 +7,8 @@ clippy::many_single_char_names, clippy::needless_pass_by_value, clippy::option_map_unit_fn, - clippy::trivially_copy_pass_by_ref -)] + clippy::trivially_copy_pass_by_ref, + )] #![warn(clippy::redundant_closure, clippy::needless_borrow)] use std::path::PathBuf; @@ -67,37 +67,57 @@ impl<'a> std::ops::Deref for TestStruct<'a> { } fn test_redundant_closures_containing_method_calls() { - let i = 10; - let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo()); - let e = Some(TestStruct { some_ref: &i }).map(TestStruct::foo); - let e = Some(TestStruct { some_ref: &i }).map(|a| a.trait_foo()); - let e = Some(TestStruct { some_ref: &i }).map(|a| a.trait_foo_ref()); - let e = Some(TestStruct { some_ref: &i }).map(TestTrait::trait_foo); - let e = Some(&mut vec![1, 2, 3]).map(|v| v.clear()); - let e = Some(&mut vec![1, 2, 3]).map(std::vec::Vec::clear); - unsafe { - let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo_unsafe()); + + // In TestStruct use cases + { + let i = 10; + let _ = Some(TestStruct { some_ref: &i }).map(|a| a.foo()); + let _ = Some(TestStruct { some_ref: &i }).map(TestStruct::foo); + let _ = Some(TestStruct { some_ref: &i }).map(|a| a.trait_foo()); + let _ = Some(TestStruct { some_ref: &i }).map(|a| a.trait_foo_ref()); + let _ = Some(TestStruct { some_ref: &i }).map(TestTrait::trait_foo); + let _ = Some(TestStruct { some_ref: &i }) + .as_ref() + .map(|c| c.to_ascii_uppercase()); + unsafe { + let _ = Some(TestStruct { some_ref: &i }).map(|a| a.foo_unsafe()); + } } - let e = Some("str").map(|s| s.to_string()); - let e = Some("str").map(str::to_string); - let e = Some('a').map(|s| s.to_uppercase()); - let e = Some('a').map(char::to_uppercase); - let e: std::vec::Vec = vec!['a', 'b', 'c'].iter().map(|c| c.len_utf8()).collect(); - let e: std::vec::Vec = vec!['a', 'b', 'c'].iter().map(|c| c.to_ascii_uppercase()).collect(); - let e: std::vec::Vec = vec!['a', 'b', 'c'].iter().map(char::to_ascii_uppercase).collect(); - let p = Some(PathBuf::new()); - let e = p.as_ref().and_then(|s| s.to_str()); - let c = Some(TestStruct { some_ref: &i }) - .as_ref() - .map(|c| c.to_ascii_uppercase()); + // In a function that uses TestTrait fn test_different_borrow_levels(t: &[&T]) - where - T: TestTrait, + where T: TestTrait, { t.iter().filter(|x| x.trait_foo_ref()); t.iter().map(|x| x.trait_foo_ref()); } + + // In Vector operations + { + let _ = Some(&mut vec![1, 2, 3]).map(|v| v.clear()); + let _ = Some(&mut vec![1, 2, 3]).map(std::vec::Vec::clear); + } + + // In String and Char operations + { + let _ = Some("str").map(|s| s.to_string()); + let _ = Some("str").map(str::to_string); + let _ = Some('a').map(|s| s.to_uppercase()); + let _ = Some('a').map(char::to_uppercase); + } + + // In Iterator Maps + { + let _: std::vec::Vec = vec!['a', 'b', 'c'].iter().map(|c| c.len_utf8()).collect(); + let _: std::vec::Vec = vec!['a', 'b', 'c'].iter().map(|c| c.to_ascii_uppercase()).collect(); + let _: std::vec::Vec = vec!['a', 'b', 'c'].iter().map(char::to_ascii_uppercase).collect(); + } + + // In other Cases + { + let p = Some(PathBuf::new()); + let _ = p.as_ref().and_then(|s| s.to_str()); + } } fn meta(f: F) diff --git a/tests/ui/eta.stderr b/tests/ui/eta.stderr index 77423694f815..36dc5e00f212 100644 --- a/tests/ui/eta.stderr +++ b/tests/ui/eta.stderr @@ -33,40 +33,40 @@ LL | let e = Some(1u8).map(|a| generic(a)); | ^^^^^^^^^^^^^^ help: remove closure as shown: `generic` error: redundant closure found - --> $DIR/eta.rs:71:51 + --> $DIR/eta.rs:74:55 | -LL | let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo()); - | ^^^^^^^^^^^ help: remove closure as shown: `TestStruct::foo` +LL | let _ = Some(TestStruct { some_ref: &i }).map(|a| a.foo()); + | ^^^^^^^^^^^ help: remove closure as shown: `TestStruct::foo` error: redundant closure found - --> $DIR/eta.rs:73:51 + --> $DIR/eta.rs:76:55 | -LL | let e = Some(TestStruct { some_ref: &i }).map(|a| a.trait_foo()); - | ^^^^^^^^^^^^^^^^^ help: remove closure as shown: `TestTrait::trait_foo` +LL | let _ = Some(TestStruct { some_ref: &i }).map(|a| a.trait_foo()); + | ^^^^^^^^^^^^^^^^^ help: remove closure as shown: `TestTrait::trait_foo` error: redundant closure found - --> $DIR/eta.rs:76:42 + --> $DIR/eta.rs:97:46 | -LL | let e = Some(&mut vec![1, 2, 3]).map(|v| v.clear()); - | ^^^^^^^^^^^^^ help: remove closure as shown: `std::vec::Vec::clear` +LL | let _ = Some(&mut vec![1, 2, 3]).map(|v| v.clear()); + | ^^^^^^^^^^^^^ help: remove closure as shown: `std::vec::Vec::clear` error: redundant closure found - --> $DIR/eta.rs:81:29 + --> $DIR/eta.rs:103:33 | -LL | let e = Some("str").map(|s| s.to_string()); - | ^^^^^^^^^^^^^^^^^ help: remove closure as shown: `std::string::ToString::to_string` +LL | let _ = Some("str").map(|s| s.to_string()); + | ^^^^^^^^^^^^^^^^^ help: remove closure as shown: `std::string::ToString::to_string` error: redundant closure found - --> $DIR/eta.rs:83:27 + --> $DIR/eta.rs:105:31 | -LL | let e = Some('a').map(|s| s.to_uppercase()); - | ^^^^^^^^^^^^^^^^^^^^ help: remove closure as shown: `char::to_uppercase` +LL | let _ = Some('a').map(|s| s.to_uppercase()); + | ^^^^^^^^^^^^^^^^^^^^ help: remove closure as shown: `char::to_uppercase` error: redundant closure found - --> $DIR/eta.rs:86:65 + --> $DIR/eta.rs:112:69 | -LL | let e: std::vec::Vec = vec!['a', 'b', 'c'].iter().map(|c| c.to_ascii_uppercase()).collect(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove closure as shown: `char::to_ascii_uppercase` +LL | let _: std::vec::Vec = vec!['a', 'b', 'c'].iter().map(|c| c.to_ascii_uppercase()).collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove closure as shown: `char::to_ascii_uppercase` error: aborting due to 11 previous errors diff --git a/tests/ui/formatting.rs b/tests/ui/formatting.rs index 149f1da93966..8e0b27a9619a 100644 --- a/tests/ui/formatting.rs +++ b/tests/ui/formatting.rs @@ -1,8 +1,11 @@ #![warn(clippy::all)] -#![allow(unused_variables)] -#![allow(unused_assignments)] -#![allow(clippy::if_same_then_else)] -#![allow(clippy::deref_addrof)] +#![allow( + unused_variables, + unused_assignments, + clippy::cognitive_complexity, + clippy::if_same_then_else, + clippy::deref_addrof + )] fn foo() -> bool { true diff --git a/tests/ui/formatting.stderr b/tests/ui/formatting.stderr index 29a5c55bc34b..a1a81cd8d011 100644 --- a/tests/ui/formatting.stderr +++ b/tests/ui/formatting.stderr @@ -1,5 +1,5 @@ error: this looks like an `else {..}` but the `else` is missing - --> $DIR/formatting.rs:15:6 + --> $DIR/formatting.rs:18:6 | LL | } { | ^ @@ -8,7 +8,7 @@ LL | } { = note: to remove this lint, add the missing `else` or add a new line before the next block error: this looks like an `else if` but the `else` is missing - --> $DIR/formatting.rs:19:6 + --> $DIR/formatting.rs:22:6 | LL | } if foo() { | ^ @@ -16,7 +16,7 @@ LL | } if foo() { = note: to remove this lint, add the missing `else` or add a new line before the second `if` error: this looks like an `else if` but the `else` is missing - --> $DIR/formatting.rs:26:10 + --> $DIR/formatting.rs:29:10 | LL | } if foo() { | ^ @@ -24,7 +24,7 @@ LL | } if foo() { = note: to remove this lint, add the missing `else` or add a new line before the second `if` error: this looks like an `else if` but the `else` is missing - --> $DIR/formatting.rs:34:10 + --> $DIR/formatting.rs:37:10 | LL | } if foo() { | ^ @@ -32,7 +32,7 @@ LL | } if foo() { = note: to remove this lint, add the missing `else` or add a new line before the second `if` error: this is an `else {..}` but the formatting might hide it - --> $DIR/formatting.rs:43:6 + --> $DIR/formatting.rs:46:6 | LL | } else | ______^ @@ -42,7 +42,7 @@ LL | | { = note: to remove this lint, remove the `else` or remove the new line between `else` and `{..}` error: this is an `else {..}` but the formatting might hide it - --> $DIR/formatting.rs:48:6 + --> $DIR/formatting.rs:51:6 | LL | } | ______^ @@ -53,7 +53,7 @@ LL | | { = note: to remove this lint, remove the `else` or remove the new line between `else` and `{..}` error: this is an `else if` but the formatting might hide it - --> $DIR/formatting.rs:54:6 + --> $DIR/formatting.rs:57:6 | LL | } else | ______^ @@ -63,7 +63,7 @@ LL | | if foo() { // the span of the above error should continue here = note: to remove this lint, remove the `else` or remove the new line between `else` and `if` error: this is an `else if` but the formatting might hide it - --> $DIR/formatting.rs:59:6 + --> $DIR/formatting.rs:62:6 | LL | } | ______^ @@ -74,7 +74,7 @@ LL | | if foo() { // the span of the above error should continue here = note: to remove this lint, remove the `else` or remove the new line between `else` and `if` error: this looks like you are trying to use `.. -= ..`, but you really are doing `.. = (- ..)` - --> $DIR/formatting.rs:100:6 + --> $DIR/formatting.rs:103:6 | LL | a =- 35; | ^^^^ @@ -83,7 +83,7 @@ LL | a =- 35; = note: to remove this lint, use either `-=` or `= -` error: this looks like you are trying to use `.. *= ..`, but you really are doing `.. = (* ..)` - --> $DIR/formatting.rs:101:6 + --> $DIR/formatting.rs:104:6 | LL | a =* &191; | ^^^^ @@ -91,7 +91,7 @@ LL | a =* &191; = note: to remove this lint, use either `*=` or `= *` error: this looks like you are trying to use `.. != ..`, but you really are doing `.. = (! ..)` - --> $DIR/formatting.rs:104:6 + --> $DIR/formatting.rs:107:6 | LL | b =! false; | ^^^^ @@ -99,7 +99,7 @@ LL | b =! false; = note: to remove this lint, use either `!=` or `= !` error: possibly missing a comma here - --> $DIR/formatting.rs:113:19 + --> $DIR/formatting.rs:116:19 | LL | -1, -2, -3 // <= no comma here | ^ @@ -108,7 +108,7 @@ LL | -1, -2, -3 // <= no comma here = note: to remove this lint, add a comma or write the expr in a single line error: possibly missing a comma here - --> $DIR/formatting.rs:117:19 + --> $DIR/formatting.rs:120:19 | LL | -1, -2, -3 // <= no comma here | ^ diff --git a/tests/ui/fxhash.rs b/tests/ui/fxhash.rs deleted file mode 100644 index 7d6cb4e11790..000000000000 --- a/tests/ui/fxhash.rs +++ /dev/null @@ -1,16 +0,0 @@ -#![warn(clippy::default_hash_types)] -#![feature(rustc_private)] - -extern crate rustc_data_structures; - -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use std::collections::{HashMap, HashSet}; - -fn main() { - let _map: HashMap = HashMap::default(); - let _set: HashSet = HashSet::default(); - - // test that the lint doesn't also match the Fx variants themselves 😂 - let _fx_map: FxHashMap = FxHashMap::default(); - let _fx_set: FxHashSet = FxHashSet::default(); -} diff --git a/tests/ui/fxhash.stderr b/tests/ui/fxhash.stderr deleted file mode 100644 index a2dac6700185..000000000000 --- a/tests/ui/fxhash.stderr +++ /dev/null @@ -1,40 +0,0 @@ -error: Prefer FxHashMap over HashMap, it has better performance and we don't need any collision prevention in clippy - --> $DIR/fxhash.rs:7:24 - | -LL | use std::collections::{HashMap, HashSet}; - | ^^^^^^^ help: use: `FxHashMap` - | - = note: `-D clippy::default-hash-types` implied by `-D warnings` - -error: Prefer FxHashSet over HashSet, it has better performance and we don't need any collision prevention in clippy - --> $DIR/fxhash.rs:7:33 - | -LL | use std::collections::{HashMap, HashSet}; - | ^^^^^^^ help: use: `FxHashSet` - -error: Prefer FxHashMap over HashMap, it has better performance and we don't need any collision prevention in clippy - --> $DIR/fxhash.rs:10:15 - | -LL | let _map: HashMap = HashMap::default(); - | ^^^^^^^ help: use: `FxHashMap` - -error: Prefer FxHashMap over HashMap, it has better performance and we don't need any collision prevention in clippy - --> $DIR/fxhash.rs:10:41 - | -LL | let _map: HashMap = HashMap::default(); - | ^^^^^^^ help: use: `FxHashMap` - -error: Prefer FxHashSet over HashSet, it has better performance and we don't need any collision prevention in clippy - --> $DIR/fxhash.rs:11:15 - | -LL | let _set: HashSet = HashSet::default(); - | ^^^^^^^ help: use: `FxHashSet` - -error: Prefer FxHashSet over HashSet, it has better performance and we don't need any collision prevention in clippy - --> $DIR/fxhash.rs:11:33 - | -LL | let _set: HashSet = HashSet::default(); - | ^^^^^^^ help: use: `FxHashSet` - -error: aborting due to 6 previous errors - diff --git a/tests/ui/len_without_is_empty.rs b/tests/ui/len_without_is_empty.rs new file mode 100644 index 000000000000..3ef29dd63880 --- /dev/null +++ b/tests/ui/len_without_is_empty.rs @@ -0,0 +1,145 @@ +#![warn(clippy::len_without_is_empty)] +#![allow(dead_code, unused)] + +pub struct PubOne; + +impl PubOne { + pub fn len(self: &Self) -> isize { + 1 + } +} + +impl PubOne { + // A second impl for this struct -- the error span shouldn't mention this. + pub fn irrelevant(self: &Self) -> bool { + false + } +} + +// Identical to `PubOne`, but with an `allow` attribute on the impl complaining `len`. +pub struct PubAllowed; + +#[allow(clippy::len_without_is_empty)] +impl PubAllowed { + pub fn len(self: &Self) -> isize { + 1 + } +} + +// No `allow` attribute on this impl block, but that doesn't matter -- we only require one on the +// impl containing `len`. +impl PubAllowed { + pub fn irrelevant(self: &Self) -> bool { + false + } +} + +pub trait PubTraitsToo { + fn len(self: &Self) -> isize; +} + +impl PubTraitsToo for One { + fn len(self: &Self) -> isize { + 0 + } +} + +pub struct HasIsEmpty; + +impl HasIsEmpty { + pub fn len(self: &Self) -> isize { + 1 + } + + fn is_empty(self: &Self) -> bool { + false + } +} + +pub struct HasWrongIsEmpty; + +impl HasWrongIsEmpty { + pub fn len(self: &Self) -> isize { + 1 + } + + pub fn is_empty(self: &Self, x: u32) -> bool { + false + } +} + +struct NotPubOne; + +impl NotPubOne { + pub fn len(self: &Self) -> isize { + // No error; `len` is pub but `NotPubOne` is not exported anyway. + 1 + } +} + +struct One; + +impl One { + fn len(self: &Self) -> isize { + // No error; `len` is private; see issue #1085. + 1 + } +} + +trait TraitsToo { + fn len(self: &Self) -> isize; + // No error; `len` is private; see issue #1085. +} + +impl TraitsToo for One { + fn len(self: &Self) -> isize { + 0 + } +} + +struct HasPrivateIsEmpty; + +impl HasPrivateIsEmpty { + pub fn len(self: &Self) -> isize { + 1 + } + + fn is_empty(self: &Self) -> bool { + false + } +} + +struct Wither; + +pub trait WithIsEmpty { + fn len(self: &Self) -> isize; + fn is_empty(self: &Self) -> bool; +} + +impl WithIsEmpty for Wither { + fn len(self: &Self) -> isize { + 1 + } + + fn is_empty(self: &Self) -> bool { + false + } +} + +pub trait Empty { + fn is_empty(&self) -> bool; +} + +pub trait InheritingEmpty: Empty { + // Must not trigger `LEN_WITHOUT_IS_EMPTY`. + fn len(&self) -> isize; +} + +// This used to ICE. +pub trait Foo: Sized {} + +pub trait DependsOnFoo: Foo { + fn len(&mut self) -> usize; +} + +fn main() {} diff --git a/tests/ui/len_without_is_empty.stderr b/tests/ui/len_without_is_empty.stderr new file mode 100644 index 000000000000..4493b17a4b4e --- /dev/null +++ b/tests/ui/len_without_is_empty.stderr @@ -0,0 +1,54 @@ +error: item `PubOne` has a public `len` method but no corresponding `is_empty` method + --> $DIR/len_without_is_empty.rs:6:1 + | +LL | / impl PubOne { +LL | | pub fn len(self: &Self) -> isize { +LL | | 1 +LL | | } +LL | | } + | |_^ + | + = note: `-D clippy::len-without-is-empty` implied by `-D warnings` + +error: trait `PubTraitsToo` has a `len` method but no (possibly inherited) `is_empty` method + --> $DIR/len_without_is_empty.rs:37:1 + | +LL | / pub trait PubTraitsToo { +LL | | fn len(self: &Self) -> isize; +LL | | } + | |_^ + +error: item `HasIsEmpty` has a public `len` method but a private `is_empty` method + --> $DIR/len_without_is_empty.rs:49:1 + | +LL | / impl HasIsEmpty { +LL | | pub fn len(self: &Self) -> isize { +LL | | 1 +LL | | } +... | +LL | | } +LL | | } + | |_^ + +error: item `HasWrongIsEmpty` has a public `len` method but no corresponding `is_empty` method + --> $DIR/len_without_is_empty.rs:61:1 + | +LL | / impl HasWrongIsEmpty { +LL | | pub fn len(self: &Self) -> isize { +LL | | 1 +LL | | } +... | +LL | | } +LL | | } + | |_^ + +error: trait `DependsOnFoo` has a `len` method but no (possibly inherited) `is_empty` method + --> $DIR/len_without_is_empty.rs:141:1 + | +LL | / pub trait DependsOnFoo: Foo { +LL | | fn len(&mut self) -> usize; +LL | | } + | |_^ + +error: aborting due to 5 previous errors + diff --git a/tests/ui/len_zero.fixed b/tests/ui/len_zero.fixed new file mode 100644 index 000000000000..56109a0fa5fb --- /dev/null +++ b/tests/ui/len_zero.fixed @@ -0,0 +1,143 @@ +// run-rustfix + +#![warn(clippy::len_zero)] +#![allow(dead_code, unused, clippy::len_without_is_empty)] + +pub struct One; +struct Wither; + +trait TraitsToo { + fn len(self: &Self) -> isize; + // No error; `len` is private; see issue #1085. +} + +impl TraitsToo for One { + fn len(self: &Self) -> isize { + 0 + } +} + +pub struct HasIsEmpty; + +impl HasIsEmpty { + pub fn len(self: &Self) -> isize { + 1 + } + + fn is_empty(self: &Self) -> bool { + false + } +} + +pub struct HasWrongIsEmpty; + +impl HasWrongIsEmpty { + pub fn len(self: &Self) -> isize { + 1 + } + + pub fn is_empty(self: &Self, x: u32) -> bool { + false + } +} + +pub trait WithIsEmpty { + fn len(self: &Self) -> isize; + fn is_empty(self: &Self) -> bool; +} + +impl WithIsEmpty for Wither { + fn len(self: &Self) -> isize { + 1 + } + + fn is_empty(self: &Self) -> bool { + false + } +} + +fn main() { + let x = [1, 2]; + if x.is_empty() { + println!("This should not happen!"); + } + + if "".is_empty() {} + + let y = One; + if y.len() == 0 { + // No error; `One` does not have `.is_empty()`. + println!("This should not happen either!"); + } + + let z: &TraitsToo = &y; + if z.len() > 0 { + // No error; `TraitsToo` has no `.is_empty()` method. + println!("Nor should this!"); + } + + let has_is_empty = HasIsEmpty; + if has_is_empty.is_empty() { + println!("Or this!"); + } + if !has_is_empty.is_empty() { + println!("Or this!"); + } + if !has_is_empty.is_empty() { + println!("Or this!"); + } + if has_is_empty.is_empty() { + println!("Or this!"); + } + if !has_is_empty.is_empty() { + println!("Or this!"); + } + if has_is_empty.len() > 1 { + // No error. + println!("This can happen."); + } + if has_is_empty.len() <= 1 { + // No error. + println!("This can happen."); + } + if has_is_empty.is_empty() { + println!("Or this!"); + } + if !has_is_empty.is_empty() { + println!("Or this!"); + } + if !has_is_empty.is_empty() { + println!("Or this!"); + } + if !has_is_empty.is_empty() { + println!("Or this!"); + } + if has_is_empty.is_empty() { + println!("Or this!"); + } + if 1 < has_is_empty.len() { + // No error. + println!("This can happen."); + } + if 1 >= has_is_empty.len() { + // No error. + println!("This can happen."); + } + assert!(!has_is_empty.is_empty()); + + let with_is_empty: &WithIsEmpty = &Wither; + if with_is_empty.is_empty() { + println!("Or this!"); + } + assert!(!with_is_empty.is_empty()); + + let has_wrong_is_empty = HasWrongIsEmpty; + if has_wrong_is_empty.len() == 0 { + // No error; `HasWrongIsEmpty` does not have `.is_empty()`. + println!("Or this!"); + } +} + +fn test_slice(b: &[u8]) { + if !b.is_empty() {} +} diff --git a/tests/ui/len_zero.rs b/tests/ui/len_zero.rs index db97c2427f37..0a77f1194621 100644 --- a/tests/ui/len_zero.rs +++ b/tests/ui/len_zero.rs @@ -1,66 +1,10 @@ -#![warn(clippy::len_without_is_empty, clippy::len_zero)] -#![allow(dead_code, unused)] +// run-rustfix -pub struct PubOne; +#![warn(clippy::len_zero)] +#![allow(dead_code, unused, clippy::len_without_is_empty)] -impl PubOne { - pub fn len(self: &Self) -> isize { - 1 - } -} - -impl PubOne { - // A second impl for this struct -- the error span shouldn't mention this. - pub fn irrelevant(self: &Self) -> bool { - false - } -} - -// Identical to `PubOne`, but with an `allow` attribute on the impl complaining `len`. -pub struct PubAllowed; - -#[allow(clippy::len_without_is_empty)] -impl PubAllowed { - pub fn len(self: &Self) -> isize { - 1 - } -} - -// No `allow` attribute on this impl block, but that doesn't matter -- we only require one on the -// impl containing `len`. -impl PubAllowed { - pub fn irrelevant(self: &Self) -> bool { - false - } -} - -struct NotPubOne; - -impl NotPubOne { - pub fn len(self: &Self) -> isize { - // No error; `len` is pub but `NotPubOne` is not exported anyway. - 1 - } -} - -struct One; - -impl One { - fn len(self: &Self) -> isize { - // No error; `len` is private; see issue #1085. - 1 - } -} - -pub trait PubTraitsToo { - fn len(self: &Self) -> isize; -} - -impl PubTraitsToo for One { - fn len(self: &Self) -> isize { - 0 - } -} +pub struct One; +struct Wither; trait TraitsToo { fn len(self: &Self) -> isize; @@ -73,9 +17,9 @@ impl TraitsToo for One { } } -struct HasPrivateIsEmpty; +pub struct HasIsEmpty; -impl HasPrivateIsEmpty { +impl HasIsEmpty { pub fn len(self: &Self) -> isize { 1 } @@ -85,20 +29,18 @@ impl HasPrivateIsEmpty { } } -pub struct HasIsEmpty; +pub struct HasWrongIsEmpty; -impl HasIsEmpty { +impl HasWrongIsEmpty { pub fn len(self: &Self) -> isize { 1 } - fn is_empty(self: &Self) -> bool { + pub fn is_empty(self: &Self, x: u32) -> bool { false } } -struct Wither; - pub trait WithIsEmpty { fn len(self: &Self) -> isize; fn is_empty(self: &Self) -> bool; @@ -114,27 +56,6 @@ impl WithIsEmpty for Wither { } } -pub struct HasWrongIsEmpty; - -impl HasWrongIsEmpty { - pub fn len(self: &Self) -> isize { - 1 - } - - pub fn is_empty(self: &Self, x: u32) -> bool { - false - } -} - -pub trait Empty { - fn is_empty(&self) -> bool; -} - -pub trait InheritingEmpty: Empty { - // Must not trigger `LEN_WITHOUT_IS_EMPTY`. - fn len(&self) -> isize; -} - fn main() { let x = [1, 2]; if x.len() == 0 { @@ -220,10 +141,3 @@ fn main() { fn test_slice(b: &[u8]) { if b.len() != 0 {} } - -// This used to ICE. -pub trait Foo: Sized {} - -pub trait DependsOnFoo: Foo { - fn len(&mut self) -> usize; -} diff --git a/tests/ui/len_zero.stderr b/tests/ui/len_zero.stderr index f2ad0bb9e1e4..9a472b31e215 100644 --- a/tests/ui/len_zero.stderr +++ b/tests/ui/len_zero.stderr @@ -1,49 +1,5 @@ -error: item `PubOne` has a public `len` method but no corresponding `is_empty` method - --> $DIR/len_zero.rs:6:1 - | -LL | / impl PubOne { -LL | | pub fn len(self: &Self) -> isize { -LL | | 1 -LL | | } -LL | | } - | |_^ - | - = note: `-D clippy::len-without-is-empty` implied by `-D warnings` - -error: trait `PubTraitsToo` has a `len` method but no (possibly inherited) `is_empty` method - --> $DIR/len_zero.rs:55:1 - | -LL | / pub trait PubTraitsToo { -LL | | fn len(self: &Self) -> isize; -LL | | } - | |_^ - -error: item `HasIsEmpty` has a public `len` method but a private `is_empty` method - --> $DIR/len_zero.rs:90:1 - | -LL | / impl HasIsEmpty { -LL | | pub fn len(self: &Self) -> isize { -LL | | 1 -LL | | } -... | -LL | | } -LL | | } - | |_^ - -error: item `HasWrongIsEmpty` has a public `len` method but no corresponding `is_empty` method - --> $DIR/len_zero.rs:119:1 - | -LL | / impl HasWrongIsEmpty { -LL | | pub fn len(self: &Self) -> isize { -LL | | 1 -LL | | } -... | -LL | | } -LL | | } - | |_^ - error: length comparison to zero - --> $DIR/len_zero.rs:140:8 + --> $DIR/len_zero.rs:61:8 | LL | if x.len() == 0 { | ^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `x.is_empty()` @@ -51,90 +7,82 @@ LL | if x.len() == 0 { = note: `-D clippy::len-zero` implied by `-D warnings` error: length comparison to zero - --> $DIR/len_zero.rs:144:8 + --> $DIR/len_zero.rs:65:8 | LL | if "".len() == 0 {} | ^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `"".is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:159:8 + --> $DIR/len_zero.rs:80:8 | LL | if has_is_empty.len() == 0 { | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:162:8 + --> $DIR/len_zero.rs:83:8 | LL | if has_is_empty.len() != 0 { | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:165:8 + --> $DIR/len_zero.rs:86:8 | LL | if has_is_empty.len() > 0 { | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to one - --> $DIR/len_zero.rs:168:8 + --> $DIR/len_zero.rs:89:8 | LL | if has_is_empty.len() < 1 { | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()` error: length comparison to one - --> $DIR/len_zero.rs:171:8 + --> $DIR/len_zero.rs:92:8 | LL | if has_is_empty.len() >= 1 { | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:182:8 + --> $DIR/len_zero.rs:103:8 | LL | if 0 == has_is_empty.len() { | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:185:8 + --> $DIR/len_zero.rs:106:8 | LL | if 0 != has_is_empty.len() { | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:188:8 + --> $DIR/len_zero.rs:109:8 | LL | if 0 < has_is_empty.len() { | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to one - --> $DIR/len_zero.rs:191:8 + --> $DIR/len_zero.rs:112:8 | LL | if 1 <= has_is_empty.len() { | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to one - --> $DIR/len_zero.rs:194:8 + --> $DIR/len_zero.rs:115:8 | LL | if 1 > has_is_empty.len() { | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:208:8 + --> $DIR/len_zero.rs:129:8 | LL | if with_is_empty.len() == 0 { | ^^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `with_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:221:8 + --> $DIR/len_zero.rs:142:8 | LL | if b.len() != 0 {} | ^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!b.is_empty()` -error: trait `DependsOnFoo` has a `len` method but no (possibly inherited) `is_empty` method - --> $DIR/len_zero.rs:227:1 - | -LL | / pub trait DependsOnFoo: Foo { -LL | | fn len(&mut self) -> usize; -LL | | } - | |_^ - -error: aborting due to 19 previous errors +error: aborting due to 14 previous errors diff --git a/tests/ui/lint_without_lint_pass.rs b/tests/ui/lint_without_lint_pass.rs index a6f10a006dbd..81b639848915 100644 --- a/tests/ui/lint_without_lint_pass.rs +++ b/tests/ui/lint_without_lint_pass.rs @@ -3,7 +3,7 @@ #[macro_use] extern crate rustc; -use rustc::lint; +use rustc::lint::{LintArray, LintPass}; #[macro_use] extern crate clippy_lints; @@ -21,8 +21,8 @@ declare_clippy_lint! { } pub struct Pass; -impl lint::LintPass for Pass { - fn get_lints(&self) -> lint::LintArray { +impl LintPass for Pass { + fn get_lints(&self) -> LintArray { lint_array!(TEST_LINT_REGISTERED) } @@ -31,4 +31,9 @@ impl lint::LintPass for Pass { } } +declare_lint_pass!(Pass2 => [TEST_LINT_REGISTERED]); + +pub struct Pass3; +impl_lint_pass!(Pass3 => [TEST_LINT_REGISTERED]); + fn main() {} diff --git a/tests/ui/map_clone.fixed b/tests/ui/map_clone.fixed index d804e838d5a6..7ba4ac7d5a38 100644 --- a/tests/ui/map_clone.fixed +++ b/tests/ui/map_clone.fixed @@ -10,6 +10,8 @@ fn main() { let _: Vec = vec![String::new()].iter().cloned().collect(); let _: Vec = vec![42, 43].iter().cloned().collect(); let _: Option = Some(Box::new(16)).map(|b| *b); + let _: Option = Some(&16).copied(); + let _: Option = Some(&1).copied(); // Don't lint these let v = vec![5_i8; 6]; diff --git a/tests/ui/map_clone.rs b/tests/ui/map_clone.rs index d98cd939d8cc..9a7be3da2067 100644 --- a/tests/ui/map_clone.rs +++ b/tests/ui/map_clone.rs @@ -10,6 +10,8 @@ fn main() { let _: Vec = vec![String::new()].iter().map(|x| x.clone()).collect(); let _: Vec = vec![42, 43].iter().map(|&x| x).collect(); let _: Option = Some(Box::new(16)).map(|b| *b); + let _: Option = Some(&16).map(|b| *b); + let _: Option = Some(&1).map(|x| x.clone()); // Don't lint these let v = vec![5_i8; 6]; diff --git a/tests/ui/map_clone.stderr b/tests/ui/map_clone.stderr index db7fa4f52fce..fb0c636d3ba0 100644 --- a/tests/ui/map_clone.stderr +++ b/tests/ui/map_clone.stderr @@ -18,11 +18,23 @@ error: You are using an explicit closure for cloning elements LL | let _: Vec = vec![42, 43].iter().map(|&x| x).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider calling the dedicated `cloned` method: `vec![42, 43].iter().cloned()` +error: You are using an explicit closure for copying elements + --> $DIR/map_clone.rs:13:26 + | +LL | let _: Option = Some(&16).map(|b| *b); + | ^^^^^^^^^^^^^^^^^^^^^ help: Consider calling the dedicated `copied` method: `Some(&16).copied()` + +error: You are using an explicit closure for copying elements + --> $DIR/map_clone.rs:14:25 + | +LL | let _: Option = Some(&1).map(|x| x.clone()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider calling the dedicated `copied` method: `Some(&1).copied()` + error: You are needlessly cloning iterator elements - --> $DIR/map_clone.rs:23:29 + --> $DIR/map_clone.rs:25:29 | LL | let _ = std::env::args().map(|v| v.clone()); | ^^^^^^^^^^^^^^^^^^^ help: Remove the map call -error: aborting due to 4 previous errors +error: aborting due to 6 previous errors diff --git a/tests/ui/match_as_ref.fixed b/tests/ui/match_as_ref.fixed new file mode 100644 index 000000000000..75085367f961 --- /dev/null +++ b/tests/ui/match_as_ref.fixed @@ -0,0 +1,14 @@ +// run-rustfix + +#![allow(unused)] +#![warn(clippy::match_as_ref)] + +fn match_as_ref() { + let owned: Option<()> = None; + let borrowed: Option<&()> = owned.as_ref(); + + let mut mut_owned: Option<()> = None; + let borrow_mut: Option<&mut ()> = mut_owned.as_mut(); +} + +fn main() {} diff --git a/tests/ui/match_as_ref.rs b/tests/ui/match_as_ref.rs new file mode 100644 index 000000000000..62c06f352514 --- /dev/null +++ b/tests/ui/match_as_ref.rs @@ -0,0 +1,20 @@ +// run-rustfix + +#![allow(unused)] +#![warn(clippy::match_as_ref)] + +fn match_as_ref() { + let owned: Option<()> = None; + let borrowed: Option<&()> = match owned { + None => None, + Some(ref v) => Some(v), + }; + + let mut mut_owned: Option<()> = None; + let borrow_mut: Option<&mut ()> = match mut_owned { + None => None, + Some(ref mut v) => Some(v), + }; +} + +fn main() {} diff --git a/tests/ui/match_as_ref.stderr b/tests/ui/match_as_ref.stderr new file mode 100644 index 000000000000..09115b85d35b --- /dev/null +++ b/tests/ui/match_as_ref.stderr @@ -0,0 +1,24 @@ +error: use as_ref() instead + --> $DIR/match_as_ref.rs:8:33 + | +LL | let borrowed: Option<&()> = match owned { + | _________________________________^ +LL | | None => None, +LL | | Some(ref v) => Some(v), +LL | | }; + | |_____^ help: try this: `owned.as_ref()` + | + = note: `-D clippy::match-as-ref` implied by `-D warnings` + +error: use as_mut() instead + --> $DIR/match_as_ref.rs:14:39 + | +LL | let borrow_mut: Option<&mut ()> = match mut_owned { + | _______________________________________^ +LL | | None => None, +LL | | Some(ref mut v) => Some(v), +LL | | }; + | |_____^ help: try this: `mut_owned.as_mut()` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/matches.rs b/tests/ui/matches.rs index b711367d123c..a7bcc9190b85 100644 --- a/tests/ui/matches.rs +++ b/tests/ui/matches.rs @@ -1,6 +1,11 @@ #![feature(exclusive_range_pattern)] #![warn(clippy::all)] -#![allow(unused, clippy::redundant_pattern_matching, clippy::too_many_lines)] +#![allow( + unused, + clippy::redundant_pattern_matching, + clippy::too_many_lines, + clippy::cognitive_complexity + )] #![warn(clippy::match_same_arms)] fn dummy() {} @@ -136,20 +141,6 @@ fn match_wild_err_arm() { } } -fn match_as_ref() { - let owned: Option<()> = None; - let borrowed: Option<&()> = match owned { - None => None, - Some(ref v) => Some(v), - }; - - let mut mut_owned: Option<()> = None; - let borrow_mut: Option<&mut ()> = match mut_owned { - None => None, - Some(ref mut v) => Some(v), - }; -} - macro_rules! foo_variant( ($idx:expr) => (Foo::get($idx).unwrap()) ); diff --git a/tests/ui/matches.stderr b/tests/ui/matches.stderr index b4159f7a68d0..c91961678690 100644 --- a/tests/ui/matches.stderr +++ b/tests/ui/matches.stderr @@ -1,5 +1,5 @@ error: you don't need to add `&` to all patterns - --> $DIR/matches.rs:11:9 + --> $DIR/matches.rs:16:9 | LL | / match v { LL | | &Some(v) => println!("{:?}", v), @@ -16,7 +16,7 @@ LL | None => println!("none"), | error: you don't need to add `&` to all patterns - --> $DIR/matches.rs:22:5 + --> $DIR/matches.rs:27:5 | LL | / match tup { LL | | &(v, 1) => println!("{}", v), @@ -30,7 +30,7 @@ LL | (v, 1) => println!("{}", v), | error: you don't need to add `&` to both the expression and the patterns - --> $DIR/matches.rs:28:5 + --> $DIR/matches.rs:33:5 | LL | / match &w { LL | | &Some(v) => println!("{:?}", v), @@ -45,7 +45,7 @@ LL | None => println!("none"), | error: you don't need to add `&` to all patterns - --> $DIR/matches.rs:39:5 + --> $DIR/matches.rs:44:5 | LL | / if let &None = a { LL | | println!("none"); @@ -57,7 +57,7 @@ LL | if let None = *a { | ^^^^ ^^ error: you don't need to add `&` to both the expression and the patterns - --> $DIR/matches.rs:44:5 + --> $DIR/matches.rs:49:5 | LL | / if let &None = &b { LL | | println!("none"); @@ -69,7 +69,7 @@ LL | if let None = b { | ^^^^ ^ error: Err(_) will match all errors, maybe not a good idea - --> $DIR/matches.rs:55:9 + --> $DIR/matches.rs:60:9 | LL | Err(_) => panic!("err"), | ^^^^^^ @@ -78,26 +78,26 @@ LL | Err(_) => panic!("err"), = note: to remove this warning, match each error separately or use unreachable macro error: this `match` has identical arm bodies - --> $DIR/matches.rs:54:18 + --> $DIR/matches.rs:59:18 | LL | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | = note: `-D clippy::match-same-arms` implied by `-D warnings` note: same as this - --> $DIR/matches.rs:53:18 + --> $DIR/matches.rs:58:18 | LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:53:18 + --> $DIR/matches.rs:58:18 | LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: Err(_) will match all errors, maybe not a good idea - --> $DIR/matches.rs:61:9 + --> $DIR/matches.rs:66:9 | LL | Err(_) => panic!(), | ^^^^^^ @@ -105,25 +105,25 @@ LL | Err(_) => panic!(), = note: to remove this warning, match each error separately or use unreachable macro error: this `match` has identical arm bodies - --> $DIR/matches.rs:60:18 + --> $DIR/matches.rs:65:18 | LL | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:59:18 + --> $DIR/matches.rs:64:18 | LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:59:18 + --> $DIR/matches.rs:64:18 | LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: Err(_) will match all errors, maybe not a good idea - --> $DIR/matches.rs:67:9 + --> $DIR/matches.rs:72:9 | LL | Err(_) => { | ^^^^^^ @@ -131,155 +131,133 @@ LL | Err(_) => { = note: to remove this warning, match each error separately or use unreachable macro error: this `match` has identical arm bodies - --> $DIR/matches.rs:66:18 + --> $DIR/matches.rs:71:18 | LL | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:65:18 + --> $DIR/matches.rs:70:18 | LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:65:18 + --> $DIR/matches.rs:70:18 | LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:75:18 + --> $DIR/matches.rs:80:18 | LL | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:74:18 + --> $DIR/matches.rs:79:18 | LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:74:18 + --> $DIR/matches.rs:79:18 | LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:82:18 + --> $DIR/matches.rs:87:18 | LL | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:81:18 + --> $DIR/matches.rs:86:18 | LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:81:18 + --> $DIR/matches.rs:86:18 | LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:88:18 + --> $DIR/matches.rs:93:18 | LL | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:87:18 + --> $DIR/matches.rs:92:18 | LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:87:18 + --> $DIR/matches.rs:92:18 | LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:94:18 + --> $DIR/matches.rs:99:18 | LL | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:93:18 + --> $DIR/matches.rs:98:18 | LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:93:18 + --> $DIR/matches.rs:98:18 | LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:117:29 + --> $DIR/matches.rs:122:29 | LL | (Ok(_), Some(x)) => println!("ok {}", x), | ^^^^^^^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:116:29 + --> $DIR/matches.rs:121:29 | LL | (Ok(x), Some(_)) => println!("ok {}", x), | ^^^^^^^^^^^^^^^^^^^^ note: consider refactoring into `(Ok(x), Some(_)) | (Ok(_), Some(x))` - --> $DIR/matches.rs:116:29 + --> $DIR/matches.rs:121:29 | LL | (Ok(x), Some(_)) => println!("ok {}", x), | ^^^^^^^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:132:18 + --> $DIR/matches.rs:137:18 | LL | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:131:18 + --> $DIR/matches.rs:136:18 | LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ note: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:131:18 + --> $DIR/matches.rs:136:18 | LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) -error: use as_ref() instead - --> $DIR/matches.rs:141:33 - | -LL | let borrowed: Option<&()> = match owned { - | _________________________________^ -LL | | None => None, -LL | | Some(ref v) => Some(v), -LL | | }; - | |_____^ help: try this: `owned.as_ref()` - | - = note: `-D clippy::match-as-ref` implied by `-D warnings` - -error: use as_mut() instead - --> $DIR/matches.rs:147:39 - | -LL | let borrow_mut: Option<&mut ()> = match mut_owned { - | _______________________________________^ -LL | | None => None, -LL | | Some(ref mut v) => Some(v), -LL | | }; - | |_____^ help: try this: `mut_owned.as_mut()` - error: you don't need to add `&` to all patterns - --> $DIR/matches.rs:174:5 + --> $DIR/matches.rs:165:5 | LL | / match foo_variant!(0) { LL | | &Foo::A => println!("A"), @@ -292,5 +270,5 @@ LL | match *foo_variant!(0) { LL | Foo::A => println!("A"), | -error: aborting due to 20 previous errors +error: aborting due to 18 previous errors diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index 673176911a9a..395271b37ebe 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -148,7 +148,6 @@ impl Mul for T { /// Checks implementation of the following lints: /// * `OPTION_MAP_UNWRAP_OR` /// * `OPTION_MAP_UNWRAP_OR_ELSE` -/// * `OPTION_MAP_OR_NONE` #[rustfmt::skip] fn option_methods() { let opt = Some(1); @@ -204,15 +203,6 @@ fn option_methods() { // Macro case. // Should not lint. let _ = opt_map!(opt, |x| x + 1).unwrap_or_else(|| 0); - - // Check `OPTION_MAP_OR_NONE`. - // Single line case. - let _ = opt.map_or(None, |x| Some(x + 1)); - // Multi-line case. - let _ = opt.map_or(None, |x| { - Some(x + 1) - } - ); } /// Checks implementation of `FILTER_NEXT` lint. @@ -278,3 +268,21 @@ fn main() { let opt = Some(0); let _ = opt.unwrap(); } + +struct Foo(u8); +#[rustfmt::skip] +fn test_or_with_ctors() { + let opt = Some(1); + let opt_opt = Some(Some(1)); + // we also test for const promotion, this makes sure we don't hit that + let two = 2; + + let _ = opt_opt.unwrap_or(Some(2)); + let _ = opt_opt.unwrap_or(Some(two)); + let _ = opt.ok_or(Some(2)); + let _ = opt.ok_or(Some(two)); + let _ = opt.ok_or(Foo(2)); + let _ = opt.ok_or(Foo(two)); + let _ = opt.or(Some(2)); + let _ = opt.or(Some(two)); +} diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index b86220f5dc26..ba93be5f4623 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -29,7 +29,7 @@ LL | fn new(self) -> Self { | ^^^^ error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/methods.rs:158:13 + --> $DIR/methods.rs:157:13 | LL | let _ = opt.map(|x| x + 1) | _____________^ @@ -41,7 +41,7 @@ LL | | .unwrap_or(0); = note: replace `map(|x| x + 1).unwrap_or(0)` with `map_or(0, |x| x + 1)` error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/methods.rs:162:13 + --> $DIR/methods.rs:161:13 | LL | let _ = opt.map(|x| { | _____________^ @@ -51,7 +51,7 @@ LL | | ).unwrap_or(0); | |____________________________^ error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/methods.rs:166:13 + --> $DIR/methods.rs:165:13 | LL | let _ = opt.map(|x| x + 1) | _____________^ @@ -61,7 +61,7 @@ LL | | }); | |__________________^ error: called `map(f).unwrap_or(None)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:171:13 + --> $DIR/methods.rs:170:13 | LL | let _ = opt.map(|x| Some(x + 1)).unwrap_or(None); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -69,7 +69,7 @@ LL | let _ = opt.map(|x| Some(x + 1)).unwrap_or(None); = note: replace `map(|x| Some(x + 1)).unwrap_or(None)` with `and_then(|x| Some(x + 1))` error: called `map(f).unwrap_or(None)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:173:13 + --> $DIR/methods.rs:172:13 | LL | let _ = opt.map(|x| { | _____________^ @@ -79,7 +79,7 @@ LL | | ).unwrap_or(None); | |_____________________^ error: called `map(f).unwrap_or(None)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:177:13 + --> $DIR/methods.rs:176:13 | LL | let _ = opt | _____________^ @@ -90,7 +90,7 @@ LL | | .unwrap_or(None); = note: replace `map(|x| Some(x + 1)).unwrap_or(None)` with `and_then(|x| Some(x + 1))` error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/methods.rs:188:13 + --> $DIR/methods.rs:187:13 | LL | let _ = Some("prefix").map(|p| format!("{}.", p)).unwrap_or(id); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -98,7 +98,7 @@ LL | let _ = Some("prefix").map(|p| format!("{}.", p)).unwrap_or(id); = note: replace `map(|p| format!("{}.", p)).unwrap_or(id)` with `map_or(id, |p| format!("{}.", p))` error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/methods.rs:192:13 + --> $DIR/methods.rs:191:13 | LL | let _ = opt.map(|x| x + 1) | _____________^ @@ -110,7 +110,7 @@ LL | | .unwrap_or_else(|| 0); = note: replace `map(|x| x + 1).unwrap_or_else(|| 0)` with `map_or_else(|| 0, |x| x + 1)` error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/methods.rs:196:13 + --> $DIR/methods.rs:195:13 | LL | let _ = opt.map(|x| { | _____________^ @@ -120,7 +120,7 @@ LL | | ).unwrap_or_else(|| 0); | |____________________________________^ error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/methods.rs:200:13 + --> $DIR/methods.rs:199:13 | LL | let _ = opt.map(|x| x + 1) | _____________^ @@ -129,32 +129,8 @@ LL | | 0 LL | | ); | |_________________^ -error: called `map_or(None, f)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:210:13 - | -LL | let _ = opt.map_or(None, |x| Some(x + 1)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using and_then instead: `opt.and_then(|x| Some(x + 1))` - | - = note: `-D clippy::option-map-or-none` implied by `-D warnings` - -error: called `map_or(None, f)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:212:13 - | -LL | let _ = opt.map_or(None, |x| { - | _____________^ -LL | | Some(x + 1) -LL | | } -LL | | ); - | |_________________^ -help: try using and_then instead - | -LL | let _ = opt.and_then(|x| { -LL | Some(x + 1) -LL | }); - | - error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:224:13 + --> $DIR/methods.rs:214:13 | LL | let _ = v.iter().filter(|&x| *x < 0).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -163,7 +139,7 @@ LL | let _ = v.iter().filter(|&x| *x < 0).next(); = note: replace `filter(|&x| *x < 0).next()` with `find(|&x| *x < 0)` error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:227:13 + --> $DIR/methods.rs:217:13 | LL | let _ = v.iter().filter(|&x| { | _____________^ @@ -173,7 +149,7 @@ LL | | ).next(); | |___________________________^ error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:243:13 + --> $DIR/methods.rs:233:13 | LL | let _ = v.iter().find(|&x| *x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -182,7 +158,7 @@ LL | let _ = v.iter().find(|&x| *x < 0).is_some(); = note: replace `find(|&x| *x < 0).is_some()` with `any(|&x| *x < 0)` error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:246:13 + --> $DIR/methods.rs:236:13 | LL | let _ = v.iter().find(|&x| { | _____________^ @@ -192,7 +168,7 @@ LL | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:252:13 + --> $DIR/methods.rs:242:13 | LL | let _ = v.iter().position(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -200,7 +176,7 @@ LL | let _ = v.iter().position(|&x| x < 0).is_some(); = note: replace `position(|&x| x < 0).is_some()` with `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:255:13 + --> $DIR/methods.rs:245:13 | LL | let _ = v.iter().position(|&x| { | _____________^ @@ -210,7 +186,7 @@ LL | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:261:13 + --> $DIR/methods.rs:251:13 | LL | let _ = v.iter().rposition(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -218,7 +194,7 @@ LL | let _ = v.iter().rposition(|&x| x < 0).is_some(); = note: replace `rposition(|&x| x < 0).is_some()` with `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:264:13 + --> $DIR/methods.rs:254:13 | LL | let _ = v.iter().rposition(|&x| { | _____________^ @@ -228,12 +204,12 @@ LL | | ).is_some(); | |______________________________^ error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:279:13 + --> $DIR/methods.rs:269:13 | LL | let _ = opt.unwrap(); | ^^^^^^^^^^^^ | = note: `-D clippy::option-unwrap-used` implied by `-D warnings` -error: aborting due to 25 previous errors +error: aborting due to 23 previous errors diff --git a/tests/ui/module_name_repetitions.rs b/tests/ui/module_name_repetitions.rs index 1719845cb21b..669bf01a84c1 100644 --- a/tests/ui/module_name_repetitions.rs +++ b/tests/ui/module_name_repetitions.rs @@ -1,3 +1,5 @@ +// compile-flags: --test + #![warn(clippy::module_name_repetitions)] #![allow(dead_code)] @@ -13,4 +15,12 @@ mod foo { pub struct Foobar; } +#[cfg(test)] +mod test { + #[test] + fn it_works() { + assert_eq!(2 + 2, 4); + } +} + fn main() {} diff --git a/tests/ui/module_name_repetitions.stderr b/tests/ui/module_name_repetitions.stderr index 5bce2c9ba602..bdd217a969c0 100644 --- a/tests/ui/module_name_repetitions.stderr +++ b/tests/ui/module_name_repetitions.stderr @@ -1,5 +1,5 @@ error: item name starts with its containing module's name - --> $DIR/module_name_repetitions.rs:6:5 + --> $DIR/module_name_repetitions.rs:8:5 | LL | pub fn foo_bar() {} | ^^^^^^^^^^^^^^^^^^^ @@ -7,25 +7,25 @@ LL | pub fn foo_bar() {} = note: `-D clippy::module-name-repetitions` implied by `-D warnings` error: item name ends with its containing module's name - --> $DIR/module_name_repetitions.rs:7:5 + --> $DIR/module_name_repetitions.rs:9:5 | LL | pub fn bar_foo() {} | ^^^^^^^^^^^^^^^^^^^ error: item name starts with its containing module's name - --> $DIR/module_name_repetitions.rs:8:5 + --> $DIR/module_name_repetitions.rs:10:5 | LL | pub struct FooCake {} | ^^^^^^^^^^^^^^^^^^^^^ error: item name ends with its containing module's name - --> $DIR/module_name_repetitions.rs:9:5 + --> $DIR/module_name_repetitions.rs:11:5 | LL | pub enum CakeFoo {} | ^^^^^^^^^^^^^^^^^^^ error: item name starts with its containing module's name - --> $DIR/module_name_repetitions.rs:10:5 + --> $DIR/module_name_repetitions.rs:12:5 | LL | pub struct Foo7Bar; | ^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/option_map_or_none.fixed b/tests/ui/option_map_or_none.fixed new file mode 100644 index 000000000000..e637f973c2ea --- /dev/null +++ b/tests/ui/option_map_or_none.fixed @@ -0,0 +1,14 @@ +// run-rustfix + +fn main() { + let opt = Some(1); + + // Check `OPTION_MAP_OR_NONE`. + // Single line case. + let _ = opt.and_then(|x| Some(x + 1)); + // Multi-line case. + #[rustfmt::skip] + let _ = opt.and_then(|x| { + Some(x + 1) + }); +} diff --git a/tests/ui/option_map_or_none.rs b/tests/ui/option_map_or_none.rs new file mode 100644 index 000000000000..4b9b247880a0 --- /dev/null +++ b/tests/ui/option_map_or_none.rs @@ -0,0 +1,14 @@ +// run-rustfix + +fn main() { + let opt = Some(1); + + // Check `OPTION_MAP_OR_NONE`. + // Single line case. + let _ = opt.map_or(None, |x| Some(x + 1)); + // Multi-line case. + #[rustfmt::skip] + let _ = opt.map_or(None, |x| { + Some(x + 1) + }); +} diff --git a/tests/ui/option_map_or_none.stderr b/tests/ui/option_map_or_none.stderr new file mode 100644 index 000000000000..66ed1e9f0451 --- /dev/null +++ b/tests/ui/option_map_or_none.stderr @@ -0,0 +1,25 @@ +error: called `map_or(None, f)` on an Option value. This can be done more directly by calling `and_then(f)` instead + --> $DIR/option_map_or_none.rs:8:13 + | +LL | let _ = opt.map_or(None, |x| Some(x + 1)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using and_then instead: `opt.and_then(|x| Some(x + 1))` + | + = note: `-D clippy::option-map-or-none` implied by `-D warnings` + +error: called `map_or(None, f)` on an Option value. This can be done more directly by calling `and_then(f)` instead + --> $DIR/option_map_or_none.rs:11:13 + | +LL | let _ = opt.map_or(None, |x| { + | _____________^ +LL | | Some(x + 1) +LL | | }); + | |_________________________^ +help: try using and_then instead + | +LL | let _ = opt.and_then(|x| { +LL | Some(x + 1) +LL | }); + | + +error: aborting due to 2 previous errors + diff --git a/tests/ui/or_fun_call.rs b/tests/ui/or_fun_call.rs index 562120c3ea0f..d33c41ac5b3d 100644 --- a/tests/ui/or_fun_call.rs +++ b/tests/ui/or_fun_call.rs @@ -1,7 +1,6 @@ #![warn(clippy::or_fun_call)] -use std::collections::BTreeMap; -use std::collections::HashMap; +use std::collections::{BTreeMap,HashMap}; /// Checks implementation of the `OR_FUN_CALL` lint. fn or_fun_call() { diff --git a/tests/ui/or_fun_call.stderr b/tests/ui/or_fun_call.stderr index 40ae09cc20e7..e51cb731070e 100644 --- a/tests/ui/or_fun_call.stderr +++ b/tests/ui/or_fun_call.stderr @@ -1,5 +1,5 @@ error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:31:22 + --> $DIR/or_fun_call.rs:30:22 | LL | with_constructor.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(make)` @@ -7,67 +7,67 @@ LL | with_constructor.unwrap_or(make()); = note: `-D clippy::or-fun-call` implied by `-D warnings` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/or_fun_call.rs:34:5 + --> $DIR/or_fun_call.rs:33:5 | LL | with_new.unwrap_or(Vec::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_new.unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:37:21 + --> $DIR/or_fun_call.rs:36:21 | LL | with_const_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:40:14 + --> $DIR/or_fun_call.rs:39:14 | LL | with_err.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| make())` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:43:19 + --> $DIR/or_fun_call.rs:42:19 | LL | with_err_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/or_fun_call.rs:46:5 + --> $DIR/or_fun_call.rs:45:5 | LL | with_default_trait.unwrap_or(Default::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_trait.unwrap_or_default()` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/or_fun_call.rs:49:5 + --> $DIR/or_fun_call.rs:48:5 | LL | with_default_type.unwrap_or(u64::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_type.unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:52:14 + --> $DIR/or_fun_call.rs:51:14 | LL | with_vec.unwrap_or(vec![]); | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| vec![])` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:57:21 + --> $DIR/or_fun_call.rs:56:21 | LL | without_default.unwrap_or(Foo::new()); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(Foo::new)` error: use of `or_insert` followed by a function call - --> $DIR/or_fun_call.rs:60:19 + --> $DIR/or_fun_call.rs:59:19 | LL | map.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)` error: use of `or_insert` followed by a function call - --> $DIR/or_fun_call.rs:63:21 + --> $DIR/or_fun_call.rs:62:21 | LL | btree.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:66:21 + --> $DIR/or_fun_call.rs:65:21 | LL | let _ = stringy.unwrap_or("".to_owned()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "".to_owned())` diff --git a/tests/ui/path_buf_push_overwrite.fixed b/tests/ui/path_buf_push_overwrite.fixed new file mode 100644 index 000000000000..ef8856830fc9 --- /dev/null +++ b/tests/ui/path_buf_push_overwrite.fixed @@ -0,0 +1,8 @@ +// run-rustfix +use std::path::PathBuf; + +#[warn(clippy::all, clippy::path_buf_push_overwrite)] +fn main() { + let mut x = PathBuf::from("/foo"); + x.push("bar"); +} diff --git a/tests/ui/path_buf_push_overwrite.rs b/tests/ui/path_buf_push_overwrite.rs new file mode 100644 index 000000000000..6e2d483f4541 --- /dev/null +++ b/tests/ui/path_buf_push_overwrite.rs @@ -0,0 +1,8 @@ +// run-rustfix +use std::path::PathBuf; + +#[warn(clippy::all, clippy::path_buf_push_overwrite)] +fn main() { + let mut x = PathBuf::from("/foo"); + x.push("/bar"); +} diff --git a/tests/ui/path_buf_push_overwrite.stderr b/tests/ui/path_buf_push_overwrite.stderr new file mode 100644 index 000000000000..09b18d71baf9 --- /dev/null +++ b/tests/ui/path_buf_push_overwrite.stderr @@ -0,0 +1,10 @@ +error: Calling `push` with '/' or '/' (file system root) will overwrite the previous path definition + --> $DIR/path_buf_push_overwrite.rs:7:12 + | +LL | x.push("/bar"); + | ^^^^^^ help: try: `"bar"` + | + = note: `-D clippy::path-buf-push-overwrite` implied by `-D warnings` + +error: aborting due to previous error + diff --git a/tests/ui/toplevel_ref_arg.rs b/tests/ui/toplevel_ref_arg.rs index 3bc0448234ef..a412c387a0dd 100644 --- a/tests/ui/toplevel_ref_arg.rs +++ b/tests/ui/toplevel_ref_arg.rs @@ -22,4 +22,8 @@ fn main() { let (ref x, _) = (1, 2); // ok, not top level println!("The answer is {}.", x); + + // Make sure that allowing the lint works + #[allow(clippy::toplevel_ref_arg)] + let ref mut x = 1_234_543; } diff --git a/tests/ui/used_underscore_binding.rs b/tests/ui/used_underscore_binding.rs index 550e16a4a204..87542252e1fb 100644 --- a/tests/ui/used_underscore_binding.rs +++ b/tests/ui/used_underscore_binding.rs @@ -1,7 +1,17 @@ +// aux-build:proc_macro_derive.rs + #![warn(clippy::all)] #![allow(clippy::blacklisted_name)] #![warn(clippy::used_underscore_binding)] +#[macro_use] +extern crate proc_macro_derive; + +// This should not trigger the lint. There's underscore binding inside the external derive that +// would trigger the `used_underscore_binding` lint. +#[derive(DeriveSomething)] +struct Baz; + macro_rules! test_macro { () => {{ let _foo = 42; @@ -51,7 +61,7 @@ fn unused_underscore_complex(mut _foo: u32) -> u32 { 1 } -///Test that we do not lint for multiple underscores +/// Test that we do not lint for multiple underscores fn multiple_underscores(__foo: u32) -> u32 { __foo + 1 } diff --git a/tests/ui/used_underscore_binding.stderr b/tests/ui/used_underscore_binding.stderr index 2e2f2056d840..8216a3c66e5b 100644 --- a/tests/ui/used_underscore_binding.stderr +++ b/tests/ui/used_underscore_binding.stderr @@ -1,5 +1,5 @@ error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used. - --> $DIR/used_underscore_binding.rs:14:5 + --> $DIR/used_underscore_binding.rs:24:5 | LL | _foo + 1 | ^^^^ @@ -7,25 +7,25 @@ LL | _foo + 1 = note: `-D clippy::used-underscore-binding` implied by `-D warnings` error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used. - --> $DIR/used_underscore_binding.rs:19:20 + --> $DIR/used_underscore_binding.rs:29:20 | LL | println!("{}", _foo); | ^^^^ error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used. - --> $DIR/used_underscore_binding.rs:20:16 + --> $DIR/used_underscore_binding.rs:30:16 | LL | assert_eq!(_foo, _foo); | ^^^^ error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used. - --> $DIR/used_underscore_binding.rs:20:22 + --> $DIR/used_underscore_binding.rs:30:22 | LL | assert_eq!(_foo, _foo); | ^^^^ error: used binding `_underscore_field` which is prefixed with an underscore. A leading underscore signals that a binding will not be used. - --> $DIR/used_underscore_binding.rs:33:5 + --> $DIR/used_underscore_binding.rs:43:5 | LL | s._underscore_field += 1; | ^^^^^^^^^^^^^^^^^^^