From e4524ac4de5327a4c25a3ba8f0fcdd0ccfc7523d Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 5 Sep 2017 11:33:04 +0200 Subject: [PATCH 1/3] Run nightly rustfmt --- clippy_lints/src/approx_const.rs | 4 +- clippy_lints/src/arithmetic.rs | 15 +- clippy_lints/src/array_indexing.rs | 46 ++- clippy_lints/src/assign_ops.rs | 40 +- clippy_lints/src/attrs.rs | 31 +- clippy_lints/src/bit_mask.rs | 202 +++++----- clippy_lints/src/blacklisted_name.rs | 4 +- clippy_lints/src/block_in_if_condition.rs | 20 +- clippy_lints/src/booleans.rs | 112 +++--- clippy_lints/src/bytecount.rs | 17 +- clippy_lints/src/collapsible_if.rs | 15 +- clippy_lints/src/consts.rs | 72 ++-- clippy_lints/src/copies.rs | 42 +-- clippy_lints/src/cyclomatic_complexity.rs | 30 +- clippy_lints/src/derive.rs | 42 +-- clippy_lints/src/doc.rs | 20 +- clippy_lints/src/double_parens.rs | 37 +- clippy_lints/src/drop_forget_ref.rs | 10 +- clippy_lints/src/empty_enum.rs | 5 +- clippy_lints/src/entry.rs | 13 +- clippy_lints/src/enum_clike.rs | 7 +- clippy_lints/src/enum_glob_use.rs | 2 +- clippy_lints/src/enum_variants.rs | 2 +- clippy_lints/src/eq_op.rs | 5 +- clippy_lints/src/escape.rs | 1 - clippy_lints/src/eta_reduction.rs | 9 +- clippy_lints/src/eval_order_dependence.rs | 56 ++- clippy_lints/src/format.rs | 8 +- clippy_lints/src/formatting.rs | 17 +- clippy_lints/src/functions.rs | 6 +- clippy_lints/src/identity_op.rs | 13 +- .../src/if_let_redundant_pattern_matching.rs | 28 +- clippy_lints/src/infinite_iter.rs | 70 ++-- clippy_lints/src/is_unit_expr.rs | 25 +- clippy_lints/src/items_after_statements.rs | 9 +- clippy_lints/src/large_enum_variant.rs | 19 +- clippy_lints/src/len_zero.rs | 66 ++-- clippy_lints/src/lib.rs | 15 +- clippy_lints/src/lifetimes.rs | 45 +-- clippy_lints/src/literal_digit_grouping.rs | 50 ++- clippy_lints/src/loops.rs | 307 ++++++++------- clippy_lints/src/map_clone.rs | 32 +- clippy_lints/src/matches.rs | 118 +++--- clippy_lints/src/mem_forget.rs | 3 +- clippy_lints/src/methods.rs | 92 +++-- clippy_lints/src/minmax.rs | 8 +- clippy_lints/src/misc.rs | 48 ++- clippy_lints/src/misc_early.rs | 42 +-- clippy_lints/src/missing_doc.rs | 38 +- clippy_lints/src/mut_mut.rs | 31 +- clippy_lints/src/mut_reference.rs | 43 ++- clippy_lints/src/mutex_atomic.rs | 4 +- clippy_lints/src/needless_bool.rs | 38 +- clippy_lints/src/needless_borrow.rs | 34 +- clippy_lints/src/needless_borrowed_ref.rs | 4 +- clippy_lints/src/needless_continue.rs | 41 +- clippy_lints/src/needless_pass_by_value.rs | 35 +- clippy_lints/src/new_without_default.rs | 61 ++- clippy_lints/src/no_effect.rs | 99 +++-- clippy_lints/src/non_expressive_names.rs | 67 ++-- clippy_lints/src/ok_if_let.rs | 2 +- clippy_lints/src/open_options.rs | 15 +- clippy_lints/src/panic.rs | 2 +- clippy_lints/src/precedence.rs | 6 +- clippy_lints/src/print.rs | 4 +- clippy_lints/src/ptr.rs | 24 +- clippy_lints/src/ranges.rs | 4 +- clippy_lints/src/reference.rs | 2 +- clippy_lints/src/regex.rs | 72 ++-- clippy_lints/src/returns.rs | 14 +- clippy_lints/src/serde_api.rs | 2 +- clippy_lints/src/shadow.rs | 116 +++--- clippy_lints/src/should_assert_eq.rs | 2 +- clippy_lints/src/strings.rs | 14 +- clippy_lints/src/temporary_assignment.rs | 7 +- clippy_lints/src/transmute.rs | 169 ++++----- clippy_lints/src/types.rs | 354 ++++++++---------- clippy_lints/src/unicode.rs | 2 +- clippy_lints/src/unsafe_removed_from_name.rs | 12 +- clippy_lints/src/unused_io_amount.rs | 17 +- clippy_lints/src/unused_label.rs | 12 +- clippy_lints/src/use_self.rs | 6 +- clippy_lints/src/utils/author.rs | 66 ++-- clippy_lints/src/utils/conf.rs | 23 +- clippy_lints/src/utils/higher.rs | 72 ++-- clippy_lints/src/utils/hir_utils.rs | 19 +- clippy_lints/src/utils/inspector.rs | 23 +- clippy_lints/src/utils/internal_lints.rs | 37 +- clippy_lints/src/utils/mod.rs | 201 +++++----- clippy_lints/src/utils/sugg.rs | 58 +-- clippy_lints/src/vec.rs | 12 +- clippy_lints/src/zero_div_zero.rs | 2 +- mini-macro/src/lib.rs | 7 +- src/main.rs | 45 +-- tests/compile-test.rs | 6 +- tests/dogfood.rs | 2 +- tests/issue-825.rs | 8 +- tests/matches.rs | 24 +- tests/needless_continue_helpers.rs | 3 +- 99 files changed, 1792 insertions(+), 2049 deletions(-) diff --git a/clippy_lints/src/approx_const.rs b/clippy_lints/src/approx_const.rs index cbe12e58119d..9d5d87dc4b32 100644 --- a/clippy_lints/src/approx_const.rs +++ b/clippy_lints/src/approx_const.rs @@ -1,7 +1,7 @@ use rustc::lint::*; use rustc::hir::*; use std::f64::consts as f64; -use syntax::ast::{Lit, LitKind, FloatTy}; +use syntax::ast::{FloatTy, Lit, LitKind}; use syntax::symbol; use utils::span_lint; @@ -91,7 +91,7 @@ fn check_known_consts(cx: &LateContext, e: &Expr, s: &symbol::Symbol, module: &s e.span, &format!( "approximate value of `{}::consts::{}` found. \ - Consider using it directly", + Consider using it directly", module, &name ), diff --git a/clippy_lints/src/arithmetic.rs b/clippy_lints/src/arithmetic.rs index 8c370213f808..a551ebf046bd 100644 --- a/clippy_lints/src/arithmetic.rs +++ b/clippy_lints/src/arithmetic.rs @@ -55,8 +55,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Arithmetic { match expr.node { hir::ExprBinary(ref op, ref l, ref r) => { match op.node { - hir::BiAnd | hir::BiOr | hir::BiBitAnd | hir::BiBitOr | hir::BiBitXor | hir::BiShl | - hir::BiShr | hir::BiEq | hir::BiLt | hir::BiLe | hir::BiNe | hir::BiGe | hir::BiGt => return, + hir::BiAnd | + hir::BiOr | + hir::BiBitAnd | + hir::BiBitOr | + hir::BiBitXor | + hir::BiShl | + hir::BiShr | + hir::BiEq | + hir::BiLt | + hir::BiLe | + hir::BiNe | + hir::BiGe | + hir::BiGt => return, _ => (), } let (l_ty, r_ty) = (cx.tables.expr_ty(l), cx.tables.expr_ty(r)); diff --git a/clippy_lints/src/array_indexing.rs b/clippy_lints/src/array_indexing.rs index 422935fa0672..5815f6456864 100644 --- a/clippy_lints/src/array_indexing.rs +++ b/clippy_lints/src/array_indexing.rs @@ -3,7 +3,7 @@ use rustc::middle::const_val::ConstVal; use rustc::ty; use rustc::ty::subst::Substs; use rustc_const_eval::ConstContext; -use rustc_const_math::{ConstUsize, ConstIsize, ConstInt}; +use rustc_const_math::{ConstInt, ConstIsize, ConstUsize}; use rustc::hir; use syntax::ast::RangeLimits; use utils::{self, higher}; @@ -124,29 +124,27 @@ fn to_const_range( }; let end = match *end { - Some(Some(ConstVal::Integral(x))) => { - if limits == RangeLimits::Closed { - match x { - ConstInt::U8(_) => (x + ConstInt::U8(1)), - ConstInt::U16(_) => (x + ConstInt::U16(1)), - ConstInt::U32(_) => (x + ConstInt::U32(1)), - ConstInt::U64(_) => (x + ConstInt::U64(1)), - ConstInt::U128(_) => (x + ConstInt::U128(1)), - ConstInt::Usize(ConstUsize::Us16(_)) => (x + ConstInt::Usize(ConstUsize::Us16(1))), - ConstInt::Usize(ConstUsize::Us32(_)) => (x + ConstInt::Usize(ConstUsize::Us32(1))), - ConstInt::Usize(ConstUsize::Us64(_)) => (x + ConstInt::Usize(ConstUsize::Us64(1))), - ConstInt::I8(_) => (x + ConstInt::I8(1)), - ConstInt::I16(_) => (x + ConstInt::I16(1)), - ConstInt::I32(_) => (x + ConstInt::I32(1)), - ConstInt::I64(_) => (x + ConstInt::I64(1)), - ConstInt::I128(_) => (x + ConstInt::I128(1)), - ConstInt::Isize(ConstIsize::Is16(_)) => (x + ConstInt::Isize(ConstIsize::Is16(1))), - ConstInt::Isize(ConstIsize::Is32(_)) => (x + ConstInt::Isize(ConstIsize::Is32(1))), - ConstInt::Isize(ConstIsize::Is64(_)) => (x + ConstInt::Isize(ConstIsize::Is64(1))), - }.expect("such a big array is not realistic") - } else { - x - } + Some(Some(ConstVal::Integral(x))) => if limits == RangeLimits::Closed { + match x { + ConstInt::U8(_) => (x + ConstInt::U8(1)), + ConstInt::U16(_) => (x + ConstInt::U16(1)), + ConstInt::U32(_) => (x + ConstInt::U32(1)), + ConstInt::U64(_) => (x + ConstInt::U64(1)), + ConstInt::U128(_) => (x + ConstInt::U128(1)), + ConstInt::Usize(ConstUsize::Us16(_)) => (x + ConstInt::Usize(ConstUsize::Us16(1))), + ConstInt::Usize(ConstUsize::Us32(_)) => (x + ConstInt::Usize(ConstUsize::Us32(1))), + ConstInt::Usize(ConstUsize::Us64(_)) => (x + ConstInt::Usize(ConstUsize::Us64(1))), + ConstInt::I8(_) => (x + ConstInt::I8(1)), + ConstInt::I16(_) => (x + ConstInt::I16(1)), + ConstInt::I32(_) => (x + ConstInt::I32(1)), + ConstInt::I64(_) => (x + ConstInt::I64(1)), + ConstInt::I128(_) => (x + ConstInt::I128(1)), + ConstInt::Isize(ConstIsize::Is16(_)) => (x + ConstInt::Isize(ConstIsize::Is16(1))), + ConstInt::Isize(ConstIsize::Is32(_)) => (x + ConstInt::Isize(ConstIsize::Is32(1))), + ConstInt::Isize(ConstIsize::Is64(_)) => (x + ConstInt::Isize(ConstIsize::Is64(1))), + }.expect("such a big array is not realistic") + } else { + x }, Some(_) => return None, None => array_size, diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index 759bb9f12ec1..33a1d94f420f 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -1,7 +1,7 @@ use rustc::hir; use rustc::lint::*; use syntax::ast; -use utils::{span_lint_and_then, snippet_opt, SpanlessEq, get_trait_def_id, implements_trait}; +use utils::{get_trait_def_id, implements_trait, snippet_opt, span_lint_and_then, SpanlessEq}; use utils::{higher, sugg}; /// **What it does:** Checks for compound assignment operations (`+=` and @@ -88,19 +88,21 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { if let hir::ExprBinary(binop, ref l, ref r) = rhs.node { if op.node == binop.node { let lint = |assignee: &hir::Expr, rhs: &hir::Expr| { - span_lint_and_then(cx, - MISREFACTORED_ASSIGN_OP, - expr.span, - "variable appears on both sides of an assignment operation", - |db| if let (Some(snip_a), Some(snip_r)) = - (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span)) { - db.span_suggestion(expr.span, - "replace it with", - format!("{} {}= {}", - snip_a, - op.node.as_str(), - snip_r)); - }); + span_lint_and_then( + cx, + MISREFACTORED_ASSIGN_OP, + expr.span, + "variable appears on both sides of an assignment operation", + |db| if let (Some(snip_a), Some(snip_r)) = + (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span)) + { + db.span_suggestion( + expr.span, + "replace it with", + format!("{} {}= {}", snip_a, op.node.as_str(), snip_r), + ); + }, + ); }; // lhs op= l op r if SpanlessEq::new(cx).ignore_fn().eq_expr(lhs, l) { @@ -167,8 +169,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { BitXor: BiBitXor, Shr: BiShr, Shl: BiShl - ) - { + ) { span_lint_and_then( cx, ASSIGN_OP_PATTERN, @@ -193,7 +194,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { // a = b commutative_op a if SpanlessEq::new(cx).ignore_fn().eq_expr(assignee, r) { match op.node { - hir::BiAdd | hir::BiMul | hir::BiAnd | hir::BiOr | hir::BiBitXor | hir::BiBitAnd | + hir::BiAdd | + hir::BiMul | + hir::BiAnd | + hir::BiOr | + hir::BiBitXor | + hir::BiBitAnd | hir::BiBitOr => { lint(assignee, l); }, diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 86d722266017..12339c039d96 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -7,7 +7,7 @@ use rustc::ty::{self, TyCtxt}; use semver::Version; use syntax::ast::{Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem, NestedMetaItemKind}; use syntax::codemap::Span; -use utils::{in_macro, match_def_path, paths, span_lint, span_lint_and_then, snippet_opt}; +use utils::{in_macro, match_def_path, paths, snippet_opt, span_lint, span_lint_and_then}; /// **What it does:** Checks for items annotated with `#[inline(always)]`, /// unless the annotated function is empty or simply panics. @@ -110,8 +110,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass { check_attrs(cx, item.span, &item.name, &item.attrs) } match item.node { - ItemExternCrate(_) | - ItemUse(_, _) => { + ItemExternCrate(_) | ItemUse(_, _) => { for attr in &item.attrs { if let Some(ref lint_list) = attr.meta_item_list() { if let Some(name) = attr.name() { @@ -196,14 +195,13 @@ fn is_relevant_block(tcx: TyCtxt, tables: &ty::TypeckTables, block: &Block) -> b if let Some(stmt) = block.stmts.first() { match stmt.node { StmtDecl(_, _) => true, - StmtExpr(ref expr, _) | - StmtSemi(ref expr, _) => is_relevant_expr(tcx, tables, expr), + StmtExpr(ref expr, _) | StmtSemi(ref expr, _) => is_relevant_expr(tcx, tables, expr), } } 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(tcx, tables, e)) } } @@ -211,15 +209,12 @@ fn is_relevant_expr(tcx: TyCtxt, tables: &ty::TypeckTables, expr: &Expr) -> bool match expr.node { ExprBlock(ref block) => is_relevant_block(tcx, tables, block), ExprRet(Some(ref e)) => is_relevant_expr(tcx, tables, e), - ExprRet(None) | - ExprBreak(_, None) => false, - ExprCall(ref path_expr, _) => { - if let ExprPath(ref qpath) = path_expr.node { - let fun_id = tables.qpath_def(qpath, path_expr.hir_id).def_id(); - !match_def_path(tcx, fun_id, &paths::BEGIN_PANIC) - } else { - true - } + ExprRet(None) | ExprBreak(_, None) => false, + ExprCall(ref path_expr, _) => if let ExprPath(ref qpath) = path_expr.node { + let fun_id = tables.qpath_def(qpath, path_expr.hir_id).def_id(); + !match_def_path(tcx, fun_id, &paths::BEGIN_PANIC) + } else { + true }, _ => true, } diff --git a/clippy_lints/src/bit_mask.rs b/clippy_lints/src/bit_mask.rs index 6e5a18240cb9..ecb12b60a16d 100644 --- a/clippy_lints/src/bit_mask.rs +++ b/clippy_lints/src/bit_mask.rs @@ -158,118 +158,100 @@ fn check_compare(cx: &LateContext, bit_op: &Expr, cmp_op: BinOp_, cmp_value: u12 fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_, mask_value: u128, cmp_value: u128, span: &Span) { match cmp_op { - BiEq | BiNe => { - match bit_op { - BiBitAnd => { - if mask_value & cmp_value != cmp_value { - if cmp_value != 0 { - span_lint( - cx, - BAD_BIT_MASK, - *span, - &format!( - "incompatible bit mask: `_ & {}` can never be equal to `{}`", - mask_value, - cmp_value - ), - ); - } - } else if mask_value == 0 { - span_lint(cx, BAD_BIT_MASK, *span, "&-masking with zero"); - } - }, - BiBitOr => { - if mask_value | cmp_value != cmp_value { - span_lint( - cx, - BAD_BIT_MASK, - *span, - &format!( - "incompatible bit mask: `_ | {}` can never be equal to `{}`", - mask_value, - cmp_value - ), - ); - } - }, - _ => (), - } + BiEq | BiNe => match bit_op { + BiBitAnd => if mask_value & cmp_value != cmp_value { + if cmp_value != 0 { + span_lint( + cx, + BAD_BIT_MASK, + *span, + &format!( + "incompatible bit mask: `_ & {}` can never be equal to `{}`", + mask_value, + cmp_value + ), + ); + } + } else if mask_value == 0 { + span_lint(cx, BAD_BIT_MASK, *span, "&-masking with zero"); + }, + BiBitOr => if mask_value | cmp_value != cmp_value { + span_lint( + cx, + BAD_BIT_MASK, + *span, + &format!( + "incompatible bit mask: `_ | {}` can never be equal to `{}`", + mask_value, + cmp_value + ), + ); + }, + _ => (), }, - BiLt | BiGe => { - match bit_op { - BiBitAnd => { - if mask_value < cmp_value { - span_lint( - cx, - BAD_BIT_MASK, - *span, - &format!( - "incompatible bit mask: `_ & {}` will always be lower than `{}`", - mask_value, - cmp_value - ), - ); - } else if mask_value == 0 { - span_lint(cx, BAD_BIT_MASK, *span, "&-masking with zero"); - } - }, - BiBitOr => { - if mask_value >= cmp_value { - span_lint( - cx, - BAD_BIT_MASK, - *span, - &format!( - "incompatible bit mask: `_ | {}` will never be lower than `{}`", - mask_value, - cmp_value - ), - ); - } else { - check_ineffective_lt(cx, *span, mask_value, cmp_value, "|"); - } - }, - BiBitXor => check_ineffective_lt(cx, *span, mask_value, cmp_value, "^"), - _ => (), - } + BiLt | BiGe => match bit_op { + BiBitAnd => if mask_value < cmp_value { + span_lint( + cx, + BAD_BIT_MASK, + *span, + &format!( + "incompatible bit mask: `_ & {}` will always be lower than `{}`", + mask_value, + cmp_value + ), + ); + } else if mask_value == 0 { + span_lint(cx, BAD_BIT_MASK, *span, "&-masking with zero"); + }, + BiBitOr => if mask_value >= cmp_value { + span_lint( + cx, + BAD_BIT_MASK, + *span, + &format!( + "incompatible bit mask: `_ | {}` will never be lower than `{}`", + mask_value, + cmp_value + ), + ); + } else { + check_ineffective_lt(cx, *span, mask_value, cmp_value, "|"); + }, + BiBitXor => check_ineffective_lt(cx, *span, mask_value, cmp_value, "^"), + _ => (), }, - BiLe | BiGt => { - match bit_op { - BiBitAnd => { - if mask_value <= cmp_value { - span_lint( - cx, - BAD_BIT_MASK, - *span, - &format!( - "incompatible bit mask: `_ & {}` will never be higher than `{}`", - mask_value, - cmp_value - ), - ); - } else if mask_value == 0 { - span_lint(cx, BAD_BIT_MASK, *span, "&-masking with zero"); - } - }, - BiBitOr => { - if mask_value > cmp_value { - span_lint( - cx, - BAD_BIT_MASK, - *span, - &format!( - "incompatible bit mask: `_ | {}` will always be higher than `{}`", - mask_value, - cmp_value - ), - ); - } else { - check_ineffective_gt(cx, *span, mask_value, cmp_value, "|"); - } - }, - BiBitXor => check_ineffective_gt(cx, *span, mask_value, cmp_value, "^"), - _ => (), - } + BiLe | BiGt => match bit_op { + BiBitAnd => if mask_value <= cmp_value { + span_lint( + cx, + BAD_BIT_MASK, + *span, + &format!( + "incompatible bit mask: `_ & {}` will never be higher than `{}`", + mask_value, + cmp_value + ), + ); + } else if mask_value == 0 { + span_lint(cx, BAD_BIT_MASK, *span, "&-masking with zero"); + }, + BiBitOr => if mask_value > cmp_value { + span_lint( + cx, + BAD_BIT_MASK, + *span, + &format!( + "incompatible bit mask: `_ | {}` will always be higher than `{}`", + mask_value, + cmp_value + ), + ); + } else { + check_ineffective_gt(cx, *span, mask_value, cmp_value, "|"); + }, + BiBitXor => check_ineffective_gt(cx, *span, mask_value, cmp_value, "^"), + _ => (), }, _ => (), } diff --git a/clippy_lints/src/blacklisted_name.rs b/clippy_lints/src/blacklisted_name.rs index e46d8e4855f6..114ba5fa7821 100644 --- a/clippy_lints/src/blacklisted_name.rs +++ b/clippy_lints/src/blacklisted_name.rs @@ -27,7 +27,9 @@ pub struct BlackListedName { impl BlackListedName { pub fn new(blacklist: Vec) -> Self { - Self { blacklist: blacklist } + Self { + blacklist: blacklist, + } } } diff --git a/clippy_lints/src/block_in_if_condition.rs b/clippy_lints/src/block_in_if_condition.rs index 82a3eb00ab7f..d67a1a5394e9 100644 --- a/clippy_lints/src/block_in_if_condition.rs +++ b/clippy_lints/src/block_in_if_condition.rs @@ -1,6 +1,6 @@ -use rustc::lint::{LateLintPass, LateContext, LintArray, LintPass}; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::hir::*; -use rustc::hir::intravisit::{Visitor, walk_expr, NestedVisitorMap}; +use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use utils::*; /// **What it does:** Checks for `if` conditions that use blocks to contain an @@ -93,15 +93,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlockInIfCondition { check.span, BRACED_EXPR_MESSAGE, &format!("try\nif {} {} ... ", - snippet_block(cx, ex.span, ".."), - snippet_block(cx, then.span, "..")), + snippet_block(cx, ex.span, ".."), + snippet_block(cx, then.span, "..")), ); } } else { - let span = block.expr.as_ref().map_or_else( - || block.stmts[0].span, - |e| e.span, - ); + let span = block + .expr + .as_ref() + .map_or_else(|| block.stmts[0].span, |e| e.span); if in_macro(span) || differing_macro_contexts(expr.span, span) { return; } @@ -112,8 +112,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlockInIfCondition { check.span, COMPLEX_BLOCK_MESSAGE, &format!("try\nlet res = {};\nif res {} ... ", - snippet_block(cx, block.span, ".."), - snippet_block(cx, then.span, "..")), + snippet_block(cx, block.span, ".."), + snippet_block(cx, then.span, "..")), ); } } diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index 7c7dbe808833..2587937616c8 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -1,10 +1,10 @@ -use rustc::lint::{LintArray, LateLintPass, LateContext, LintPass}; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::hir::*; use rustc::hir::intravisit::*; -use syntax::ast::{LitKind, DUMMY_NODE_ID, NodeId}; -use syntax::codemap::{DUMMY_SP, dummy_spanned, Span}; +use syntax::ast::{LitKind, NodeId, DUMMY_NODE_ID}; +use syntax::codemap::{dummy_spanned, Span, DUMMY_SP}; use syntax::util::ThinVec; -use utils::{span_lint_and_then, in_macro, snippet_opt, SpanlessEq}; +use utils::{in_macro, snippet_opt, span_lint_and_then, SpanlessEq}; /// **What it does:** Checks for boolean expressions that can be written more /// concisely. @@ -96,26 +96,23 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { if !in_macro(e.span) { match e.node { ExprUnary(UnNot, ref inner) => return Ok(Bool::Not(box self.run(inner)?)), - ExprBinary(binop, ref lhs, ref rhs) => { - match binop.node { - BiOr => return Ok(Bool::Or(self.extract(BiOr, &[lhs, rhs], Vec::new())?)), - BiAnd => return Ok(Bool::And(self.extract(BiAnd, &[lhs, rhs], Vec::new())?)), - _ => (), - } + ExprBinary(binop, ref lhs, ref rhs) => match binop.node { + BiOr => return Ok(Bool::Or(self.extract(BiOr, &[lhs, rhs], Vec::new())?)), + BiAnd => return Ok(Bool::And(self.extract(BiAnd, &[lhs, rhs], Vec::new())?)), + _ => (), }, - ExprLit(ref lit) => { - match lit.node { - LitKind::Bool(true) => return Ok(Bool::True), - LitKind::Bool(false) => return Ok(Bool::False), - _ => (), - } + ExprLit(ref lit) => match lit.node { + LitKind::Bool(true) => return Ok(Bool::True), + LitKind::Bool(false) => return Ok(Bool::False), + _ => (), }, _ => (), } } for (n, expr) in self.terminals.iter().enumerate() { if SpanlessEq::new(self.cx).ignore_fn().eq_expr(e, expr) { - #[allow(cast_possible_truncation)] return Ok(Bool::Term(n as u8)); + #[allow(cast_possible_truncation)] + return Ok(Bool::Term(n as u8)); } let negated = match e.node { ExprBinary(binop, ref lhs, ref rhs) => { @@ -141,13 +138,15 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { _ => continue, }; if SpanlessEq::new(self.cx).ignore_fn().eq_expr(&negated, expr) { - #[allow(cast_possible_truncation)] return Ok(Bool::Not(Box::new(Bool::Term(n as u8)))); + #[allow(cast_possible_truncation)] + return Ok(Bool::Not(Box::new(Bool::Term(n as u8)))); } } let n = self.terminals.len(); self.terminals.push(e); if n < 32 { - #[allow(cast_possible_truncation)] Ok(Bool::Term(n as u8)) + #[allow(cast_possible_truncation)] + Ok(Bool::Term(n as u8)) } else { Err("too many literals".to_owned()) } @@ -167,40 +166,36 @@ fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String { s.push_str("false"); s }, - Not(ref inner) => { - match **inner { - And(_) | Or(_) => { - s.push('!'); - recurse(true, cx, inner, terminals, s) - }, - Term(n) => { - if let ExprBinary(binop, ref lhs, ref rhs) = terminals[n as usize].node { - let op = match binop.node { - BiEq => " != ", - BiNe => " == ", - BiLt => " >= ", - BiGt => " <= ", - BiLe => " > ", - BiGe => " < ", - _ => { - s.push('!'); - return recurse(true, cx, inner, terminals, s); - }, - }; - s.push_str(&snip(lhs)); - s.push_str(op); - s.push_str(&snip(rhs)); - s - } else { + Not(ref inner) => match **inner { + And(_) | Or(_) => { + s.push('!'); + recurse(true, cx, inner, terminals, s) + }, + Term(n) => if let ExprBinary(binop, ref lhs, ref rhs) = terminals[n as usize].node { + let op = match binop.node { + BiEq => " != ", + BiNe => " == ", + BiLt => " >= ", + BiGt => " <= ", + BiLe => " > ", + BiGe => " < ", + _ => { s.push('!'); - recurse(false, cx, inner, terminals, s) - } - }, - _ => { - s.push('!'); - recurse(false, cx, inner, terminals, s) - }, - } + return recurse(true, cx, inner, terminals, s); + }, + }; + s.push_str(&snip(lhs)); + s.push_str(op); + s.push_str(&snip(rhs)); + s + } else { + s.push('!'); + recurse(false, cx, inner, terminals, s) + }, + _ => { + s.push('!'); + recurse(false, cx, inner, terminals, s) + }, }, And(ref v) => { if brackets { @@ -319,7 +314,6 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { cx: self.cx, }; if let Ok(expr) = h2q.run(e) { - if h2q.terminals.len() > 8 { // QMC has exponentially slow behavior as the number of terminals increases // 8 is reasonable, it takes approximately 0.2 seconds. @@ -360,7 +354,7 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { db.span_help( h2q.terminals[i].span, "this expression can be optimized out by applying boolean operations to the \ - outer expression", + outer expression", ); db.span_suggestion( e.span, @@ -411,12 +405,10 @@ impl<'a, 'tcx> Visitor<'tcx> for NonminimalBoolVisitor<'a, 'tcx> { } match e.node { ExprBinary(binop, _, _) if binop.node == BiOr || binop.node == BiAnd => self.bool_expr(e), - ExprUnary(UnNot, ref inner) => { - if self.cx.tables.node_types()[inner.hir_id].is_bool() { - self.bool_expr(e); - } else { - walk_expr(self, e); - } + ExprUnary(UnNot, ref inner) => if self.cx.tables.node_types()[inner.hir_id].is_bool() { + self.bool_expr(e); + } else { + walk_expr(self, e); }, _ => walk_expr(self, e), } diff --git a/clippy_lints/src/bytecount.rs b/clippy_lints/src/bytecount.rs index 1d7afbe084dd..447214c70f88 100644 --- a/clippy_lints/src/bytecount.rs +++ b/clippy_lints/src/bytecount.rs @@ -97,23 +97,18 @@ fn get_pat_name(pat: &Pat) -> Option { match pat.node { PatKind::Binding(_, _, ref spname, _) => Some(spname.node), PatKind::Path(ref qpath) => single_segment_path(qpath).map(|ps| ps.name), - PatKind::Box(ref p) | - PatKind::Ref(ref p, _) => get_pat_name(&*p), + PatKind::Box(ref p) | PatKind::Ref(ref p, _) => get_pat_name(&*p), _ => None, } } fn get_path_name(expr: &Expr) -> Option { match expr.node { - ExprBox(ref e) | - ExprAddrOf(_, ref e) | - ExprUnary(UnOp::UnDeref, ref e) => get_path_name(e), - ExprBlock(ref b) => { - if b.stmts.is_empty() { - b.expr.as_ref().and_then(|p| get_path_name(p)) - } else { - None - } + ExprBox(ref e) | ExprAddrOf(_, ref e) | ExprUnary(UnOp::UnDeref, ref e) => get_path_name(e), + ExprBlock(ref b) => if b.stmts.is_empty() { + b.expr.as_ref().and_then(|p| get_path_name(p)) + } else { + None }, ExprPath(ref qpath) => single_segment_path(qpath).map(|ps| ps.name), _ => None, diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs index 1914b83e8989..fb0ff23cc632 100644 --- a/clippy_lints/src/collapsible_if.rs +++ b/clippy_lints/src/collapsible_if.rs @@ -15,7 +15,7 @@ use rustc::lint::*; use syntax::ast; -use utils::{in_macro, snippet_block, span_lint_and_then, span_lint_and_sugg}; +use utils::{in_macro, snippet_block, span_lint_and_sugg, span_lint_and_then}; use utils::sugg::Sugg; /// **What it does:** Checks for nested `if` statements which can be collapsed @@ -87,12 +87,10 @@ impl EarlyLintPass for CollapsibleIf { fn check_if(cx: &EarlyContext, expr: &ast::Expr) { match expr.node { - ast::ExprKind::If(ref check, ref then, ref else_) => { - if let Some(ref else_) = *else_ { - check_collapsible_maybe_if_let(cx, else_); - } else { - check_collapsible_no_if_let(cx, expr, check, then); - } + ast::ExprKind::If(ref check, ref then, ref else_) => if let Some(ref else_) = *else_ { + check_collapsible_maybe_if_let(cx, else_); + } else { + check_collapsible_no_if_let(cx, expr, check, then); }, ast::ExprKind::IfLet(_, _, _, Some(ref else_)) => { check_collapsible_maybe_if_let(cx, else_); @@ -147,8 +145,7 @@ fn expr_block(block: &ast::Block) -> Option<&ast::Expr> { if let (Some(stmt), None) = (it.next(), it.next()) { match stmt.node { - ast::StmtKind::Expr(ref expr) | - ast::StmtKind::Semi(ref expr) => Some(expr), + ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => Some(expr), _ => None, } } else { diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 0a76b95931de..de62990afd51 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -5,8 +5,8 @@ use rustc::hir::def::Def; use rustc_const_eval::lookup_const_by_id; use rustc_const_math::ConstInt; use rustc::hir::*; -use rustc::ty::{self, TyCtxt, Ty}; -use rustc::ty::subst::{Substs, Subst}; +use rustc::ty::{self, Ty, TyCtxt}; +use rustc::ty::subst::{Subst, Substs}; use std::cmp::Ordering::{self, Equal}; use std::cmp::PartialOrd; use std::hash::{Hash, Hasher}; @@ -76,7 +76,7 @@ impl PartialEq for Constant { (&Constant::Vec(ref l), &Constant::Vec(ref r)) => l == r, (&Constant::Repeat(ref lv, ref ls), &Constant::Repeat(ref rv, ref rs)) => ls == rs && lv == rv, (&Constant::Tuple(ref l), &Constant::Tuple(ref r)) => l == r, - _ => false, //TODO: Are there inter-type equalities? + _ => false, // TODO: Are there inter-type equalities? } } } @@ -110,8 +110,7 @@ impl Hash for Constant { Constant::Bool(b) => { b.hash(state); }, - Constant::Vec(ref v) | - Constant::Tuple(ref v) => { + Constant::Vec(ref v) | Constant::Tuple(ref v) => { v.hash(state); }, Constant::Repeat(ref c, l) => { @@ -125,12 +124,10 @@ impl Hash for Constant { impl PartialOrd for Constant { fn partial_cmp(&self, other: &Self) -> Option { match (self, other) { - (&Constant::Str(ref ls, ref l_sty), &Constant::Str(ref rs, ref r_sty)) => { - if l_sty == r_sty { - Some(ls.cmp(rs)) - } else { - None - } + (&Constant::Str(ref ls, ref l_sty), &Constant::Str(ref rs, ref r_sty)) => if l_sty == r_sty { + Some(ls.cmp(rs)) + } else { + None }, (&Constant::Char(ref l), &Constant::Char(ref r)) => Some(l.cmp(r)), (&Constant::Int(l), &Constant::Int(r)) => Some(l.cmp(&r)), @@ -147,15 +144,14 @@ impl PartialOrd for Constant { } }, (&Constant::Bool(ref l), &Constant::Bool(ref r)) => Some(l.cmp(r)), - (&Constant::Tuple(ref l), &Constant::Tuple(ref r)) | - (&Constant::Vec(ref l), &Constant::Vec(ref r)) => l.partial_cmp(r), - (&Constant::Repeat(ref lv, ref ls), &Constant::Repeat(ref rv, ref rs)) => { - match lv.partial_cmp(rv) { - Some(Equal) => Some(ls.cmp(rs)), - x => x, - } + (&Constant::Tuple(ref l), &Constant::Tuple(ref r)) | (&Constant::Vec(ref l), &Constant::Vec(ref r)) => { + l.partial_cmp(r) }, - _ => None, //TODO: Are there any useful inter-type orderings? + (&Constant::Repeat(ref lv, ref ls), &Constant::Repeat(ref rv, ref rs)) => match lv.partial_cmp(rv) { + Some(Equal) => Some(ls.cmp(rs)), + x => x, + }, + _ => None, // TODO: Are there any useful inter-type orderings? } } } @@ -177,18 +173,14 @@ pub fn lit_to_constant<'a, 'tcx>(lit: &LitKind, tcx: TyCtxt<'a, 'tcx, 'tcx>, mut LitKind::Byte(b) => Constant::Int(ConstInt::U8(b)), LitKind::ByteStr(ref s) => Constant::Binary(s.clone()), LitKind::Char(c) => Constant::Char(c), - LitKind::Int(n, hint) => { - match (&ty.sty, hint) { - (&ty::TyInt(ity), _) | - (_, Signed(ity)) => { - Constant::Int(ConstInt::new_signed_truncating(n as i128, ity, tcx.sess.target.int_type)) - }, - (&ty::TyUint(uty), _) | - (_, Unsigned(uty)) => { - Constant::Int(ConstInt::new_unsigned_truncating(n as u128, uty, tcx.sess.target.uint_type)) - }, - _ => bug!(), - } + LitKind::Int(n, hint) => match (&ty.sty, hint) { + (&ty::TyInt(ity), _) | (_, Signed(ity)) => { + Constant::Int(ConstInt::new_signed_truncating(n as i128, ity, tcx.sess.target.int_type)) + }, + (&ty::TyUint(uty), _) | (_, Unsigned(uty)) => { + Constant::Int(ConstInt::new_unsigned_truncating(n as u128, uty, tcx.sess.target.uint_type)) + }, + _ => bug!(), }, LitKind::Float(ref is, ty) => Constant::Float(is.to_string(), ty.into()), LitKind::FloatUnsuffixed(ref is) => Constant::Float(is.to_string(), FloatWidth::Any), @@ -262,13 +254,11 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { }; self.expr(value).map(|v| Constant::Repeat(Box::new(v), n)) }, - ExprUnary(op, ref operand) => { - self.expr(operand).and_then(|o| match op { - UnNot => constant_not(&o), - UnNeg => constant_negate(o), - UnDeref => Some(o), - }) - }, + ExprUnary(op, ref operand) => self.expr(operand).and_then(|o| match op { + UnNot => constant_not(&o), + UnNeg => constant_negate(o), + UnDeref => Some(o), + }), ExprBinary(op, ref left, ref right) => self.binop(op, left, right), // TODO: add other expressions _ => None, @@ -287,8 +277,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { fn fetch_path(&mut self, qpath: &QPath, id: HirId) -> Option { let def = self.tables.qpath_def(qpath, id); match def { - Def::Const(def_id) | - Def::AssociatedConst(def_id) => { + Def::Const(def_id) | Def::AssociatedConst(def_id) => { let substs = self.tables.node_substs(id); let substs = if self.substs.is_empty() { substs @@ -358,8 +347,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { (BiRem, Constant::Int(l), Some(Constant::Int(r))) => (l % r).ok().map(Constant::Int), (BiAnd, Constant::Bool(false), _) => Some(Constant::Bool(false)), (BiOr, Constant::Bool(true), _) => Some(Constant::Bool(true)), - (BiAnd, Constant::Bool(true), Some(r)) | - (BiOr, Constant::Bool(false), Some(r)) => Some(r), + (BiAnd, Constant::Bool(true), Some(r)) | (BiOr, Constant::Bool(false), Some(r)) => Some(r), (BiBitXor, Constant::Bool(l), Some(Constant::Bool(r))) => Some(Constant::Bool(l ^ r)), (BiBitXor, Constant::Int(l), Some(Constant::Int(r))) => (l ^ r).ok().map(Constant::Int), (BiBitAnd, Constant::Bool(l), Some(Constant::Bool(r))) => Some(Constant::Bool(l & r)), diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index f9e11d06882d..862272456ea4 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -6,7 +6,7 @@ use std::collections::hash_map::Entry; use syntax::symbol::InternedString; use syntax::util::small_vector::SmallVector; use utils::{SpanlessEq, SpanlessHash}; -use utils::{get_parent_expr, in_macro, span_lint_and_then, span_note_and_lint, snippet}; +use utils::{get_parent_expr, in_macro, snippet, span_lint_and_then, span_note_and_lint}; /// **What it does:** Checks for consecutive `if`s with the same condition. /// @@ -114,7 +114,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CopyAndPaste { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if !in_macro(expr.span) { // skip ifs directly in else, it will be checked in the parent if - if let Some(&Expr { node: ExprIf(_, _, Some(ref else_expr)), .. }) = get_parent_expr(cx, expr) { + if let Some(&Expr { + node: ExprIf(_, _, Some(ref else_expr)), + .. + }) = get_parent_expr(cx, expr) + { if else_expr.id == expr.id { return; } @@ -267,12 +271,9 @@ fn if_sequence(mut expr: &Expr) -> (SmallVector<&Expr>, SmallVector<&Block>) { fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap> { fn bindings_impl<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat, map: &mut HashMap>) { match pat.node { - PatKind::Box(ref pat) | - PatKind::Ref(ref pat, _) => bindings_impl(cx, pat, map), - PatKind::TupleStruct(_, ref pats, _) => { - for pat in pats { - bindings_impl(cx, pat, map); - } + PatKind::Box(ref pat) | PatKind::Ref(ref pat, _) => bindings_impl(cx, pat, map), + PatKind::TupleStruct(_, ref pats, _) => for pat in pats { + bindings_impl(cx, pat, map); }, PatKind::Binding(_, _, ref ident, ref as_pat) => { if let Entry::Vacant(v) = map.entry(ident.node.as_str()) { @@ -282,15 +283,11 @@ fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap { - for pat in fields { - bindings_impl(cx, &pat.node.pat, map); - } + PatKind::Struct(_, ref fields, _) => for pat in fields { + bindings_impl(cx, &pat.node.pat, map); }, - PatKind::Tuple(ref fields, _) => { - for pat in fields { - bindings_impl(cx, pat, map); - } + PatKind::Tuple(ref fields, _) => for pat in fields { + bindings_impl(cx, pat, map); }, PatKind::Slice(ref lhs, ref mid, ref rhs) => { for pat in lhs { @@ -303,10 +300,7 @@ fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap (), + PatKind::Lit(..) | PatKind::Range(..) | PatKind::Wild | PatKind::Path(..) => (), } } @@ -335,11 +329,9 @@ where for expr in exprs { match map.entry(hash(expr)) { - Entry::Occupied(o) => { - for o in o.get() { - if eq(o, expr) { - return Some((o, expr)); - } + Entry::Occupied(o) => for o in o.get() { + if eq(o, expr) { + return Some((o, expr)); } }, Entry::Vacant(v) => { diff --git a/clippy_lints/src/cyclomatic_complexity.rs b/clippy_lints/src/cyclomatic_complexity.rs index edfa5e0fb611..ede9dcb1fbd2 100644 --- a/clippy_lints/src/cyclomatic_complexity.rs +++ b/clippy_lints/src/cyclomatic_complexity.rs @@ -4,11 +4,11 @@ use rustc::cfg::CFG; use rustc::lint::*; use rustc::hir::*; use rustc::ty; -use rustc::hir::intravisit::{Visitor, walk_expr, NestedVisitorMap}; +use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use syntax::ast::{Attribute, NodeId}; use syntax::codemap::Span; -use utils::{in_macro, LimitStack, span_help_and_lint, paths, match_type, is_allowed}; +use utils::{in_macro, is_allowed, match_type, paths, span_help_and_lint, LimitStack}; /// **What it does:** Checks for methods with high cyclomatic complexity. /// @@ -31,7 +31,9 @@ pub struct CyclomaticComplexity { impl CyclomaticComplexity { pub fn new(limit: u64) -> Self { - Self { limit: LimitStack::new(limit) } + Self { + limit: LimitStack::new(limit), + } } } @@ -125,18 +127,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CyclomaticComplexity { } fn enter_lint_attrs(&mut self, cx: &LateContext<'a, 'tcx>, attrs: &'tcx [Attribute]) { - self.limit.push_attrs( - cx.sess(), - attrs, - "cyclomatic_complexity", - ); + self.limit + .push_attrs(cx.sess(), attrs, "cyclomatic_complexity"); } fn exit_lint_attrs(&mut self, cx: &LateContext<'a, 'tcx>, attrs: &'tcx [Attribute]) { - self.limit.pop_attrs( - cx.sess(), - attrs, - "cyclomatic_complexity", - ); + self.limit + .pop_attrs(cx.sess(), attrs, "cyclomatic_complexity"); } } @@ -194,7 +190,7 @@ fn report_cc_bug(_: &LateContext, cc: u64, narms: u64, div: u64, shorts: u64, re span_bug!( span, "Clippy encountered a bug calculating cyclomatic complexity: cc = {}, arms = {}, \ - div = {}, shorts = {}, returns = {}. Please file a bug report.", + div = {}, shorts = {}, returns = {}. Please file a bug report.", cc, narms, div, @@ -210,9 +206,9 @@ fn report_cc_bug(cx: &LateContext, cc: u64, narms: u64, div: u64, shorts: u64, r span, &format!( "Clippy encountered a bug calculating cyclomatic complexity \ - (hide this message with `#[allow(cyclomatic_complexity)]`): \ - cc = {}, arms = {}, div = {}, shorts = {}, returns = {}. \ - Please file a bug report.", + (hide this message with `#[allow(cyclomatic_complexity)]`): \ + cc = {}, arms = {}, div = {}, shorts = {}, returns = {}. \ + Please file a bug report.", cc, narms, div, diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 36576365eac8..b70e591f9957 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -3,7 +3,7 @@ use rustc::ty::{self, Ty}; use rustc::hir::*; use syntax::codemap::Span; use utils::paths; -use utils::{is_automatically_derived, span_lint_and_then, match_path, is_copy}; +use utils::{is_automatically_derived, is_copy, match_path, span_lint_and_then}; /// **What it does:** Checks for deriving `Hash` but implementing `PartialEq` /// explicitly. @@ -141,31 +141,31 @@ fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, item: &Item, trait_ref ty::TyAdt(def, _) if def.is_union() => return, // Some types are not Clone by default but could be cloned “by hand” if necessary - ty::TyAdt(def, substs) => { - for variant in &def.variants { - for field in &variant.fields { - match field.ty(cx.tcx, substs).sty { - ty::TyArray(_, size) if size > 32 => { - return; - }, - ty::TyFnPtr(..) => { - return; - }, - ty::TyTuple(tys, _) if tys.len() > 12 => { - return; - }, - _ => (), - } + ty::TyAdt(def, substs) => for variant in &def.variants { + for field in &variant.fields { + match field.ty(cx.tcx, substs).sty { + ty::TyArray(_, size) if size > 32 => { + return; + }, + ty::TyFnPtr(..) => { + return; + }, + ty::TyTuple(tys, _) if tys.len() > 12 => { + return; + }, + _ => (), } } }, _ => (), } - span_lint_and_then(cx, - EXPL_IMPL_CLONE_ON_COPY, - item.span, - "you are implementing `Clone` explicitly on a `Copy` type", - |db| { db.span_note(item.span, "consider deriving `Clone` or removing `Copy`"); }); + span_lint_and_then( + cx, + EXPL_IMPL_CLONE_ON_COPY, + item.span, + "you are implementing `Clone` explicitly on a `Copy` type", + |db| { db.span_note(item.span, "consider deriving `Clone` or removing `Copy`"); }, + ); } } diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 8977ea437d14..170ca5cf0079 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -2,7 +2,7 @@ use itertools::Itertools; use pulldown_cmark; use rustc::lint::*; use syntax::ast; -use syntax::codemap::{Span, BytePos}; +use syntax::codemap::{BytePos, Span}; use syntax_pos::Pos; use utils::span_lint; @@ -37,7 +37,9 @@ pub struct Doc { impl Doc { pub fn new(valid_idents: Vec) -> Self { - Self { valid_idents: valid_idents } + Self { + valid_idents: valid_idents, + } } } @@ -196,17 +198,13 @@ fn check_doc<'a, Events: Iterator)>>( for (offset, event) in docs { match event { - Start(CodeBlock(_)) | - Start(Code) => in_code = true, - End(CodeBlock(_)) | - End(Code) => in_code = false, - Start(_tag) | End(_tag) => (), // We don't care about other tags - Html(_html) | - InlineHtml(_html) => (), // HTML is weird, just ignore it + Start(CodeBlock(_)) | Start(Code) => in_code = true, + End(CodeBlock(_)) | End(Code) => in_code = false, + Start(_tag) | End(_tag) => (), // We don't care about other tags + Html(_html) | InlineHtml(_html) => (), // HTML is weird, just ignore it SoftBreak => (), HardBreak => (), - FootnoteReference(text) | - Text(text) => { + FootnoteReference(text) | Text(text) => { if !in_code { let index = match spans.binary_search_by(|c| c.0.cmp(&offset)) { Ok(o) => o, diff --git a/clippy_lints/src/double_parens.rs b/clippy_lints/src/double_parens.rs index 5ef166388783..be5e056d5dfb 100644 --- a/clippy_lints/src/double_parens.rs +++ b/clippy_lints/src/double_parens.rs @@ -1,5 +1,5 @@ use syntax::ast::*; -use rustc::lint::{EarlyContext, LintContext, LintArray, LintPass, EarlyLintPass}; +use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass}; /// **What it does:** Checks for unnecessary double parentheses. /// @@ -31,29 +31,22 @@ impl LintPass for DoubleParens { impl EarlyLintPass for DoubleParens { fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) { match expr.node { - ExprKind::Paren(ref in_paren) => { - match in_paren.node { - ExprKind::Paren(_) | - ExprKind::Tup(_) => { - cx.span_lint(DOUBLE_PARENS, expr.span, "Consider removing unnecessary double parentheses"); - }, - _ => {}, + ExprKind::Paren(ref in_paren) => match in_paren.node { + ExprKind::Paren(_) | ExprKind::Tup(_) => { + cx.span_lint(DOUBLE_PARENS, expr.span, "Consider removing unnecessary double parentheses"); + }, + _ => {}, + }, + ExprKind::Call(_, ref params) => if params.len() == 1 { + let param = ¶ms[0]; + if let ExprKind::Paren(_) = param.node { + cx.span_lint(DOUBLE_PARENS, param.span, "Consider removing unnecessary double parentheses"); } }, - ExprKind::Call(_, ref params) => { - if params.len() == 1 { - let param = ¶ms[0]; - if let ExprKind::Paren(_) = param.node { - cx.span_lint(DOUBLE_PARENS, param.span, "Consider removing unnecessary double parentheses"); - } - } - }, - ExprKind::MethodCall(_, ref params) => { - if params.len() == 2 { - let param = ¶ms[1]; - if let ExprKind::Paren(_) = param.node { - cx.span_lint(DOUBLE_PARENS, param.span, "Consider removing unnecessary double parentheses"); - } + ExprKind::MethodCall(_, ref params) => if params.len() == 2 { + let param = ¶ms[1]; + if let ExprKind::Paren(_) = param.node { + cx.span_lint(DOUBLE_PARENS, param.span, "Consider removing unnecessary double parentheses"); } }, _ => {}, diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs index dfa8ddbab6cc..6ca04d40067a 100644 --- a/clippy_lints/src/drop_forget_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -1,7 +1,7 @@ use rustc::lint::*; use rustc::ty; use rustc::hir::*; -use utils::{match_def_path, paths, span_note_and_lint, is_copy}; +use utils::{is_copy, match_def_path, paths, span_note_and_lint}; /// **What it does:** Checks for calls to `std::mem::drop` with a reference /// instead of an owned value. @@ -96,13 +96,13 @@ declare_lint! { } const DROP_REF_SUMMARY: &str = "calls to `std::mem::drop` with a reference instead of an owned value. \ - Dropping a reference does nothing."; + Dropping a reference does nothing."; const FORGET_REF_SUMMARY: &str = "calls to `std::mem::forget` with a reference instead of an owned value. \ - Forgetting a reference does nothing."; + Forgetting a reference does nothing."; const DROP_COPY_SUMMARY: &str = "calls to `std::mem::drop` with a value that implements Copy. \ - Dropping a copy leaves the original intact."; + Dropping a copy leaves the original intact."; const FORGET_COPY_SUMMARY: &str = "calls to `std::mem::forget` with a value that implements Copy. \ - Forgetting a copy leaves the original intact."; + Forgetting a copy leaves the original intact."; #[allow(missing_copy_implementations)] pub struct Pass; diff --git a/clippy_lints/src/empty_enum.rs b/clippy_lints/src/empty_enum.rs index 7845c85b6872..67a4b8d4030d 100644 --- a/clippy_lints/src/empty_enum.rs +++ b/clippy_lints/src/empty_enum.rs @@ -36,9 +36,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EmptyEnum { let did = cx.tcx.hir.local_def_id(item.id); if let ItemEnum(..) = item.node { let ty = cx.tcx.type_of(did); - let adt = ty.ty_adt_def().expect( - "already checked whether this is an enum", - ); + let adt = ty.ty_adt_def() + .expect("already checked whether this is an enum"); if adt.variants.is_empty() { span_lint_and_then(cx, EMPTY_ENUM, item.span, "enum with no variants", |db| { db.span_help(item.span, "consider using the uninhabited type `!` or a wrapper around it"); diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index 80288ff22688..a3558a189e2a 100644 --- a/clippy_lints/src/entry.rs +++ b/clippy_lints/src/entry.rs @@ -1,5 +1,5 @@ use rustc::hir::*; -use rustc::hir::intravisit::{Visitor, walk_expr, NestedVisitorMap}; +use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc::lint::*; use syntax::codemap::Span; use utils::SpanlessEq; @@ -47,12 +47,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for HashMapLint { // in case of `if !m.contains_key(&k) { m.insert(k, v); }` // we can give a better error message let sole_expr = { - else_block.is_none() && - if let ExprBlock(ref then_block) = then_block.node { - (then_block.expr.is_some() as usize) + then_block.stmts.len() == 1 - } else { - true - } + else_block.is_none() && if let ExprBlock(ref then_block) = then_block.node { + (then_block.expr.is_some() as usize) + then_block.stmts.len() == 1 + } else { + true + } }; let mut visitor = InsertVisitor { diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs index e95c37b0aeef..c776681d51c4 100644 --- a/clippy_lints/src/enum_clike.rs +++ b/clippy_lints/src/enum_clike.rs @@ -51,9 +51,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnportableVariant { let did = cx.tcx.hir.body_owner_def_id(body_id); let param_env = ty::ParamEnv::empty(Reveal::UserFacing); let substs = Substs::identity_for_item(cx.tcx.global_tcx(), did); - let bad = match cx.tcx.at(expr.span).const_eval( - param_env.and((did, substs)), - ) { + let bad = match cx.tcx + .at(expr.span) + .const_eval(param_env.and((did, substs))) + { Ok(ConstVal::Integral(Usize(Us64(i)))) => u64::from(i as u32) != i, Ok(ConstVal::Integral(Isize(Is64(i)))) => i64::from(i as i32) != i, _ => false, diff --git a/clippy_lints/src/enum_glob_use.rs b/clippy_lints/src/enum_glob_use.rs index 6738f5bb63b9..9aa43653ab5f 100644 --- a/clippy_lints/src/enum_glob_use.rs +++ b/clippy_lints/src/enum_glob_use.rs @@ -1,7 +1,7 @@ //! lint on `use`ing all variants of an enum use rustc::hir::*; -use rustc::lint::{LateLintPass, LintPass, LateContext, LintArray}; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use syntax::ast::NodeId; use syntax::codemap::Span; use utils::span_lint; diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index eee4e2a7ee16..c4f7f39003e0 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -204,7 +204,7 @@ fn check_variant( &format!("All variants have the same {}fix: `{}`", what, value), &format!( "remove the {}fixes and use full paths to \ - the variants instead of glob imports", + the variants instead of glob imports", what ), ); diff --git a/clippy_lints/src/eq_op.rs b/clippy_lints/src/eq_op.rs index 84a54dd215b7..2c268c188359 100644 --- a/clippy_lints/src/eq_op.rs +++ b/clippy_lints/src/eq_op.rs @@ -1,6 +1,6 @@ use rustc::hir::*; use rustc::lint::*; -use utils::{SpanlessEq, span_lint, span_lint_and_then, multispan_sugg, snippet, implements_trait, is_copy}; +use utils::{implements_trait, is_copy, multispan_sugg, snippet, span_lint, span_lint_and_then, SpanlessEq}; /// **What it does:** Checks for equal operands to comparison, logical and /// bitwise, difference and division binary operators (`==`, `>`, etc., `&&`, @@ -82,8 +82,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { #[allow(match_same_arms)] match (&left.node, &right.node) { // do not suggest to dereference literals - (&ExprLit(..), _) | - (_, &ExprLit(..)) => {}, + (&ExprLit(..), _) | (_, &ExprLit(..)) => {}, // &foo == &bar (&ExprAddrOf(_, ref l), &ExprAddrOf(_, ref r)) => { let lty = cx.tables.expr_ty(l); diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index c6183948ef38..beb96f333cbe 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -133,7 +133,6 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { self.set.remove(&lid); } } - } fn borrow(&mut self, _: NodeId, _: Span, cmt: cmt<'tcx>, _: ty::Region, _: ty::BorrowKind, loan_cause: LoanCause) { if let Categorization::Local(lid) = cmt.cat { diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index 42524da7ffc4..0710689c3d4d 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -1,7 +1,7 @@ use rustc::lint::*; use rustc::ty; use rustc::hir::*; -use utils::{snippet_opt, span_lint_and_then, is_adjusted, iter_input_pats}; +use utils::{is_adjusted, iter_input_pats, snippet_opt, span_lint_and_then}; #[allow(missing_copy_implementations)] pub struct EtaPass; @@ -37,11 +37,8 @@ impl LintPass for EtaPass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EtaPass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { match expr.node { - ExprCall(_, ref args) | - ExprMethodCall(_, _, ref args) => { - for arg in args { - check_closure(cx, arg) - } + ExprCall(_, ref args) | ExprMethodCall(_, _, ref args) => for arg in args { + check_closure(cx, arg) }, _ => (), } diff --git a/clippy_lints/src/eval_order_dependence.rs b/clippy_lints/src/eval_order_dependence.rs index db952cd5d988..621438b9a873 100644 --- a/clippy_lints/src/eval_order_dependence.rs +++ b/clippy_lints/src/eval_order_dependence.rs @@ -1,9 +1,9 @@ use rustc::hir::def_id::DefId; -use rustc::hir::intravisit::{Visitor, walk_expr, NestedVisitorMap}; +use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc::hir::*; use rustc::ty; use rustc::lint::*; -use utils::{get_parent_expr, span_note_and_lint, span_lint}; +use utils::{get_parent_expr, span_lint, span_note_and_lint}; /// **What it does:** Checks for a read and a write to the same variable where /// whether the read occurs before or after the write depends on the evaluation @@ -62,20 +62,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EvalOrderDependence { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { // Find a write to a local variable. match expr.node { - ExprAssign(ref lhs, _) | - ExprAssignOp(_, ref lhs, _) => { - if let ExprPath(ref qpath) = lhs.node { - if let QPath::Resolved(_, ref path) = *qpath { - if path.segments.len() == 1 { - let var = cx.tables.qpath_def(qpath, lhs.hir_id).def_id(); - let mut visitor = ReadVisitor { - cx: cx, - var: var, - write_expr: expr, - last_expr: expr, - }; - check_for_unsequenced_reads(&mut visitor); - } + ExprAssign(ref lhs, _) | ExprAssignOp(_, ref lhs, _) => if let ExprPath(ref qpath) = lhs.node { + if let QPath::Resolved(_, ref path) = *qpath { + if path.segments.len() == 1 { + let var = cx.tables.qpath_def(qpath, lhs.hir_id).def_id(); + let mut visitor = ReadVisitor { + cx: cx, + var: var, + write_expr: expr, + last_expr: expr, + }; + check_for_unsequenced_reads(&mut visitor); } } }, @@ -84,13 +81,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EvalOrderDependence { } fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt) { match stmt.node { - StmtExpr(ref e, _) | - StmtSemi(ref e, _) => DivergenceVisitor { cx: cx }.maybe_walk_expr(e), - StmtDecl(ref d, _) => { - if let DeclLocal(ref local) = d.node { - if let Local { init: Some(ref e), .. } = **local { - DivergenceVisitor { cx: cx }.visit_expr(e); - } + StmtExpr(ref e, _) | StmtSemi(ref e, _) => DivergenceVisitor { cx: cx }.maybe_walk_expr(e), + StmtDecl(ref d, _) => if let DeclLocal(ref local) = d.node { + if let Local { + init: Some(ref e), .. + } = **local + { + DivergenceVisitor { cx: cx }.visit_expr(e); } }, } @@ -230,8 +227,7 @@ fn check_expr<'a, 'tcx>(vis: &mut ReadVisitor<'a, 'tcx>, expr: &'tcx Expr) -> St ExprStruct(_, _, _) => { walk_expr(vis, expr); }, - ExprBinary(op, _, _) | - ExprAssignOp(op, _, _) => { + ExprBinary(op, _, _) | ExprAssignOp(op, _, _) => { if op.node == BiAnd || op.node == BiOr { // x && y and x || y always evaluate x first, so these are // strictly sequenced. @@ -265,8 +261,7 @@ fn check_expr<'a, 'tcx>(vis: &mut ReadVisitor<'a, 'tcx>, expr: &'tcx Expr) -> St fn check_stmt<'a, 'tcx>(vis: &mut ReadVisitor<'a, 'tcx>, stmt: &'tcx Stmt) -> StopEarly { match stmt.node { - StmtExpr(ref expr, _) | - StmtSemi(ref expr, _) => check_expr(vis, expr), + StmtExpr(ref expr, _) | StmtSemi(ref expr, _) => check_expr(vis, expr), StmtDecl(ref decl, _) => { // If the declaration is of a local variable, check its initializer // expression if it has one. Otherwise, keep going. @@ -274,10 +269,9 @@ fn check_stmt<'a, 'tcx>(vis: &mut ReadVisitor<'a, 'tcx>, stmt: &'tcx Stmt) -> St DeclLocal(ref local) => Some(local), _ => None, }; - local.and_then(|local| local.init.as_ref()).map_or( - StopEarly::KeepGoing, - |expr| check_expr(vis, expr), - ) + local + .and_then(|local| local.init.as_ref()) + .map_or(StopEarly::KeepGoing, |expr| check_expr(vis, expr)) }, } } diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index fb2e04a3662d..2577e2908a8c 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -57,11 +57,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { }} }, // `format!("foo")` expansion contains `match () { () => [], }` - ExprMatch(ref matchee, _, _) => { - if let ExprTup(ref tup) = matchee.node { - if tup.is_empty() { - span_lint(cx, USELESS_FORMAT, span, "useless use of `format!`"); - } + ExprMatch(ref matchee, _, _) => if let ExprTup(ref tup) = matchee.node { + if tup.is_empty() { + span_lint(cx, USELESS_FORMAT, span, "useless use of `format!`"); } }, _ => (), diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs index e3b3bb408b33..7d7129429860 100644 --- a/clippy_lints/src/formatting.rs +++ b/clippy_lints/src/formatting.rs @@ -117,7 +117,7 @@ fn check_assign(cx: &EarlyContext, expr: &ast::Expr) { eqop_span, &format!( "this looks like you are trying to use `.. {op}= ..`, but you \ - really are doing `.. = ({op} ..)`", + really are doing `.. = ({op} ..)`", op = op ), eqop_span, @@ -142,9 +142,9 @@ fn check_else_if(cx: &EarlyContext, expr: &ast::Expr) { // the snippet should look like " else \n " with maybe comments anywhere // it’s bad when there is a ‘\n’ after the “else” if let Some(else_snippet) = snippet_opt(cx, else_span) { - let else_pos = else_snippet.find("else").expect( - "there must be a `else` here", - ); + let else_pos = else_snippet + .find("else") + .expect("there must be a `else` here"); if else_snippet[else_pos..].contains('\n') { span_note_and_lint( @@ -154,7 +154,7 @@ fn check_else_if(cx: &EarlyContext, expr: &ast::Expr) { "this is an `else if` but the formatting might hide it", else_span, "to remove this lint, remove the `else` or remove the new line between `else` \ - and `if`", + and `if`", ); } } @@ -205,7 +205,7 @@ fn check_consecutive_ifs(cx: &EarlyContext, first: &ast::Expr, second: &ast::Exp "this looks like an `else if` but the `else` is missing", else_span, "to remove this lint, add the missing `else` or add a new line before the second \ - `if`", + `if`", ); } } @@ -215,8 +215,9 @@ fn check_consecutive_ifs(cx: &EarlyContext, first: &ast::Expr, second: &ast::Exp /// Match `if` or `if let` expressions and return the `then` and `else` block. fn unsugar_if(expr: &ast::Expr) -> Option<(&P, &Option>)> { match expr.node { - ast::ExprKind::If(_, ref then, ref else_) | - ast::ExprKind::IfLet(_, _, ref then, ref else_) => Some((then, else_)), + ast::ExprKind::If(_, ref then, ref else_) | ast::ExprKind::IfLet(_, _, ref then, ref else_) => { + Some((then, else_)) + }, _ => None, } } diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index 70ff96d36d43..869e621eab63 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -6,7 +6,7 @@ use std::collections::HashSet; use syntax::ast; use syntax::abi::Abi; use syntax::codemap::Span; -use utils::{span_lint, type_is_unsafe_function, iter_input_pats}; +use utils::{iter_input_pats, span_lint, type_is_unsafe_function}; /// **What it does:** Checks for functions with too many parameters. /// @@ -60,7 +60,9 @@ pub struct Functions { impl Functions { pub fn new(threshold: u64) -> Self { - Self { threshold: threshold } + Self { + threshold: threshold, + } } } diff --git a/clippy_lints/src/identity_op.rs b/clippy_lints/src/identity_op.rs index a7c254e1e464..a409f4c7d65c 100644 --- a/clippy_lints/src/identity_op.rs +++ b/clippy_lints/src/identity_op.rs @@ -2,7 +2,7 @@ use consts::{constant_simple, Constant}; use rustc::lint::*; use rustc::hir::*; use syntax::codemap::Span; -use utils::{span_lint, snippet, in_macro}; +use utils::{in_macro, snippet, span_lint}; use syntax::attr::IntType::{SignedInt, UnsignedInt}; /// **What it does:** Checks for identity operations, e.g. `x + 0`. @@ -63,16 +63,13 @@ fn check(cx: &LateContext, e: &Expr, m: i8, span: Span, arg: Span) { if let Some(Constant::Int(v)) = constant_simple(cx, e) { if match m { 0 => v.to_u128_unchecked() == 0, - -1 => { - match v.int_type() { - SignedInt(_) => (v.to_u128_unchecked() as i128 == -1), - UnsignedInt(_) => false, - } + -1 => match v.int_type() { + SignedInt(_) => (v.to_u128_unchecked() as i128 == -1), + UnsignedInt(_) => false, }, 1 => v.to_u128_unchecked() == 1, _ => unreachable!(), - } - { + } { span_lint( cx, IDENTITY_OP, diff --git a/clippy_lints/src/if_let_redundant_pattern_matching.rs b/clippy_lints/src/if_let_redundant_pattern_matching.rs index 36411b73a623..27f41c0e6987 100644 --- a/clippy_lints/src/if_let_redundant_pattern_matching.rs +++ b/clippy_lints/src/if_let_redundant_pattern_matching.rs @@ -1,6 +1,6 @@ use rustc::lint::*; use rustc::hir::*; -use utils::{paths, span_lint_and_then, match_qpath, snippet}; +use utils::{match_qpath, paths, snippet, span_lint_and_then}; /// **What it does:*** Lint for redundant pattern matching over `Result` or /// `Option` @@ -45,11 +45,8 @@ impl LintPass for Pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - if let ExprMatch(ref op, ref arms, MatchSource::IfLetDesugar { .. }) = expr.node { - if arms[0].pats.len() == 1 { - let good_method = match arms[0].pats[0].node { PatKind::TupleStruct(ref path, ref pats, _) if pats.len() == 1 && pats[0].node == PatKind::Wild => { if match_qpath(path, &paths::RESULT_OK) { @@ -68,16 +65,21 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { _ => return, }; - span_lint_and_then(cx, - IF_LET_REDUNDANT_PATTERN_MATCHING, - arms[0].pats[0].span, - &format!("redundant pattern matching, consider using `{}`", good_method), - |db| { - let span = expr.span.with_hi(op.span.hi()); - db.span_suggestion(span, "try this", format!("if {}.{}", snippet(cx, op.span, "_"), good_method)); - }); + span_lint_and_then( + cx, + IF_LET_REDUNDANT_PATTERN_MATCHING, + arms[0].pats[0].span, + &format!("redundant pattern matching, consider using `{}`", good_method), + |db| { + let span = expr.span.with_hi(op.span.hi()); + db.span_suggestion( + span, + "try this", + format!("if {}.{}", snippet(cx, op.span, "_"), good_method), + ); + }, + ); } - } } } diff --git a/clippy_lints/src/infinite_iter.rs b/clippy_lints/src/infinite_iter.rs index d542ddb029fb..3a5bcdc78d49 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::*; -use utils::{get_trait_def_id, implements_trait, higher, match_qpath, paths, span_lint}; +use utils::{get_trait_def_id, higher, implements_trait, match_qpath, paths, span_lint}; /// **What it does:** Checks for iteration that is guaranteed to be infinite. /// @@ -66,14 +66,13 @@ enum Finiteness { Finite, } -use self::Finiteness::{Infinite, MaybeInfinite, Finite}; +use self::Finiteness::{Finite, Infinite, MaybeInfinite}; impl Finiteness { fn and(self, b: Self) -> Self { match (self, b) { (Finite, _) | (_, Finite) => Finite, - (MaybeInfinite, _) | - (_, MaybeInfinite) => MaybeInfinite, + (MaybeInfinite, _) | (_, MaybeInfinite) => MaybeInfinite, _ => Infinite, } } @@ -81,8 +80,7 @@ impl Finiteness { fn or(self, b: Self) -> Self { match (self, b) { (Infinite, _) | (_, Infinite) => Infinite, - (MaybeInfinite, _) | - (_, MaybeInfinite) => MaybeInfinite, + (MaybeInfinite, _) | (_, MaybeInfinite) => MaybeInfinite, _ => Finite, } } @@ -90,7 +88,11 @@ impl Finiteness { impl From for Finiteness { fn from(b: bool) -> Self { - if b { Infinite } else { Finite } + if b { + Infinite + } else { + Finite + } } } @@ -108,7 +110,7 @@ enum Heuristic { All, } -use self::Heuristic::{Always, First, Any, All}; +use self::Heuristic::{All, Always, Any, First}; /// a slice of (method name, number of args, heuristic, bounds) tuples /// that will be used to determine whether the method in question @@ -143,11 +145,11 @@ fn is_infinite(cx: &LateContext, expr: &Expr) -> Finiteness { for &(name, len, heuristic, cap) in HEURISTICS.iter() { if method.name == name && args.len() == len { return (match heuristic { - Always => Infinite, - First => is_infinite(cx, &args[0]), - Any => is_infinite(cx, &args[0]).or(is_infinite(cx, &args[1])), - All => is_infinite(cx, &args[0]).and(is_infinite(cx, &args[1])), - }).and(cap); + Always => Infinite, + First => is_infinite(cx, &args[0]), + Any => is_infinite(cx, &args[0]).or(is_infinite(cx, &args[1])), + All => is_infinite(cx, &args[0]).and(is_infinite(cx, &args[1])), + }).and(cap); } } if method.name == "flat_map" && args.len() == 2 { @@ -159,20 +161,15 @@ fn is_infinite(cx: &LateContext, expr: &Expr) -> Finiteness { Finite }, ExprBlock(ref block) => block.expr.as_ref().map_or(Finite, |e| is_infinite(cx, e)), - ExprBox(ref e) | - ExprAddrOf(_, ref e) => is_infinite(cx, e), - ExprCall(ref path, _) => { - if let ExprPath(ref qpath) = path.node { - match_qpath(qpath, &paths::REPEAT).into() - } else { - Finite - } - }, - ExprStruct(..) => { - higher::range(expr) - .map_or(false, |r| r.end.is_none()) - .into() + ExprBox(ref e) | ExprAddrOf(_, ref e) => is_infinite(cx, e), + ExprCall(ref path, _) => if let ExprPath(ref qpath) = path.node { + match_qpath(qpath, &paths::REPEAT).into() + } else { + Finite }, + ExprStruct(..) => higher::range(expr) + .map_or(false, |r| r.end.is_none()) + .into(), _ => Finite, } } @@ -220,23 +217,18 @@ fn complete_infinite_iter(cx: &LateContext, expr: &Expr) -> Finiteness { } } if method.name == "last" && args.len() == 1 { - let not_double_ended = get_trait_def_id(cx, - &paths::DOUBLE_ENDED_ITERATOR) - .map_or(false, |id| { - !implements_trait(cx, cx.tables.expr_ty(&args[0]), id, &[]) - }); + let not_double_ended = get_trait_def_id(cx, &paths::DOUBLE_ENDED_ITERATOR) + .map_or(false, |id| !implements_trait(cx, cx.tables.expr_ty(&args[0]), id, &[])); if not_double_ended { - return is_infinite(cx, &args[0]); + return is_infinite(cx, &args[0]); } } }, - ExprBinary(op, ref l, ref r) => { - if op.node.is_comparison() { - return is_infinite(cx, l).and(is_infinite(cx, r)).and( - MaybeInfinite, - ); - } - }, //TODO: ExprLoop + Match + ExprBinary(op, ref l, ref r) => if op.node.is_comparison() { + return is_infinite(cx, l) + .and(is_infinite(cx, r)) + .and(MaybeInfinite); + }, // TODO: ExprLoop + Match _ => (), } Finite diff --git a/clippy_lints/src/is_unit_expr.rs b/clippy_lints/src/is_unit_expr.rs index 5939cd36bf86..152612bd8ff2 100644 --- a/clippy_lints/src/is_unit_expr.rs +++ b/clippy_lints/src/is_unit_expr.rs @@ -100,12 +100,10 @@ impl EarlyLintPass for UnitExpr { } fn is_unit_expr(expr: &Expr) -> Option { match expr.node { - ExprKind::Block(ref block) => { - if check_last_stmt_in_block(block) { - Some(block.stmts[block.stmts.len() - 1].span) - } else { - None - } + ExprKind::Block(ref block) => if check_last_stmt_in_block(block) { + Some(block.stmts[block.stmts.len() - 1].span) + } else { + None }, ExprKind::If(_, ref then, ref else_) => { let check_then = check_last_stmt_in_block(then); @@ -115,7 +113,11 @@ fn is_unit_expr(expr: &Expr) -> Option { return Some(*expr_else); } } - if check_then { Some(expr.span) } else { None } + if check_then { + Some(expr.span) + } else { + None + } }, ExprKind::Match(ref _pattern, ref arms) => { for arm in arms { @@ -137,12 +139,9 @@ fn check_last_stmt_in_block(block: &Block) -> bool { // like `panic!()` match final_stmt.node { StmtKind::Expr(_) => false, - StmtKind::Semi(ref expr) => { - match expr.node { - ExprKind::Break(_, _) | - ExprKind::Ret(_) => false, - _ => true, - } + StmtKind::Semi(ref expr) => match expr.node { + ExprKind::Break(_, _) | ExprKind::Ret(_) => false, + _ => true, }, _ => true, } diff --git a/clippy_lints/src/items_after_statements.rs b/clippy_lints/src/items_after_statements.rs index f14c70dc4ddc..2aabecabff07 100644 --- a/clippy_lints/src/items_after_statements.rs +++ b/clippy_lints/src/items_after_statements.rs @@ -47,9 +47,10 @@ impl EarlyLintPass for ItemsAfterStatements { } // skip initial items - let stmts = item.stmts.iter().map(|stmt| &stmt.node).skip_while(|s| { - matches!(**s, StmtKind::Item(..)) - }); + let stmts = item.stmts + .iter() + .map(|stmt| &stmt.node) + .skip_while(|s| matches!(**s, StmtKind::Item(..))); // lint on all further items for stmt in stmts { @@ -66,7 +67,7 @@ impl EarlyLintPass for ItemsAfterStatements { ITEMS_AFTER_STATEMENTS, it.span, "adding items after statements is confusing, since items exist from the \ - start of the scope", + start of the scope", ); } } diff --git a/clippy_lints/src/large_enum_variant.rs b/clippy_lints/src/large_enum_variant.rs index 917e0b773707..ceb0cbd6688e 100644 --- a/clippy_lints/src/large_enum_variant.rs +++ b/clippy_lints/src/large_enum_variant.rs @@ -2,7 +2,7 @@ use rustc::lint::*; use rustc::hir::*; -use utils::{span_lint_and_then, snippet_opt, type_size}; +use utils::{snippet_opt, span_lint_and_then, type_size}; use rustc::ty::TypeFoldable; /// **What it does:** Checks for large size differences between variants on @@ -34,7 +34,9 @@ pub struct LargeEnumVariant { impl LargeEnumVariant { pub fn new(maximum_size_difference_allowed: u64) -> Self { - Self { maximum_size_difference_allowed: maximum_size_difference_allowed } + Self { + maximum_size_difference_allowed: maximum_size_difference_allowed, + } } } @@ -49,9 +51,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeEnumVariant { let did = cx.tcx.hir.local_def_id(item.id); if let ItemEnum(ref def, _) = item.node { let ty = cx.tcx.type_of(did); - let adt = ty.ty_adt_def().expect( - "already checked whether this is an enum", - ); + let adt = ty.ty_adt_def() + .expect("already checked whether this is an enum"); let mut smallest_variant: Option<(_, _)> = None; let mut largest_variant: Option<(_, _)> = None; @@ -90,15 +91,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeEnumVariant { |db| { if variant.fields.len() == 1 { let span = match def.variants[i].node.data { - VariantData::Struct(ref fields, _) | - VariantData::Tuple(ref fields, _) => fields[0].ty.span, + VariantData::Struct(ref fields, _) | VariantData::Tuple(ref fields, _) => { + fields[0].ty.span + }, VariantData::Unit(_) => unreachable!(), }; if let Some(snip) = snippet_opt(cx, span) { db.span_suggestion( span, "consider boxing the large fields to reduce the total size of the \ - enum", + enum", format!("Box<{}>", snip), ); return; @@ -112,7 +114,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeEnumVariant { ); } } - } } } diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index e862240da59a..9b14a44f2c04 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -91,16 +91,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LenZero { fn check_trait_items(cx: &LateContext, visited_trait: &Item, trait_items: &[TraitItemRef]) { fn is_named_self(cx: &LateContext, item: &TraitItemRef, name: &str) -> bool { - item.name == name && - if let AssociatedItemKind::Method { has_self } = item.kind { - has_self && - { - let did = cx.tcx.hir.local_def_id(item.id.node_id); - cx.tcx.fn_sig(did).inputs().skip_binder().len() == 1 - } - } else { - false + item.name == name && if let AssociatedItemKind::Method { has_self } = item.kind { + has_self && { + let did = cx.tcx.hir.local_def_id(item.id.node_id); + cx.tcx.fn_sig(did).inputs().skip_binder().len() == 1 } + } else { + false + } } // fill the set with current and super traits @@ -121,10 +119,8 @@ fn check_trait_items(cx: &LateContext, visited_trait: &Item, trait_items: &[Trai .iter() .flat_map(|&i| cx.tcx.associated_items(i)) .any(|i| { - i.kind == ty::AssociatedKind::Method && - i.method_has_self_argument && - i.name == "is_empty" && - cx.tcx.fn_sig(i.def_id).inputs().skip_binder().len() == 1 + i.kind == ty::AssociatedKind::Method && i.method_has_self_argument && i.name == "is_empty" && + cx.tcx.fn_sig(i.def_id).inputs().skip_binder().len() == 1 }); if !is_empty_method_found { @@ -143,16 +139,14 @@ fn check_trait_items(cx: &LateContext, visited_trait: &Item, trait_items: &[Trai fn check_impl_items(cx: &LateContext, item: &Item, impl_items: &[ImplItemRef]) { fn is_named_self(cx: &LateContext, item: &ImplItemRef, name: &str) -> bool { - item.name == name && - if let AssociatedItemKind::Method { has_self } = item.kind { - has_self && - { - let did = cx.tcx.hir.local_def_id(item.id.node_id); - cx.tcx.fn_sig(did).inputs().skip_binder().len() == 1 - } - } else { - false + item.name == name && if let AssociatedItemKind::Method { has_self } = item.kind { + has_self && { + let did = cx.tcx.hir.local_def_id(item.id.node_id); + cx.tcx.fn_sig(did).inputs().skip_binder().len() == 1 } + } else { + false + } } let is_empty = if let Some(is_empty) = impl_items.iter().find(|i| is_named_self(cx, i, "is_empty")) { @@ -197,7 +191,11 @@ fn check_cmp(cx: &LateContext, span: Span, left: &Expr, right: &Expr, op: &str) } fn check_len_zero(cx: &LateContext, span: Span, name: Name, args: &[Expr], lit: &Lit, op: &str) { - if let Spanned { node: LitKind::Int(0, _), .. } = *lit { + if let Spanned { + node: LitKind::Int(0, _), + .. + } = *lit + { if name == "len" && args.len() == 1 && has_is_empty(cx, &args[0]) { span_lint_and_sugg( cx, @@ -231,25 +229,19 @@ fn has_is_empty(cx: &LateContext, expr: &Expr) -> bool { /// Check the inherent impl's items for an `is_empty(self)` method. fn has_is_empty_impl(cx: &LateContext, id: DefId) -> bool { cx.tcx.inherent_impls(id).iter().any(|imp| { - cx.tcx.associated_items(*imp).any( - |item| is_is_empty(cx, &item), - ) + cx.tcx + .associated_items(*imp) + .any(|item| is_is_empty(cx, &item)) }) } let ty = &walk_ptrs_ty(cx.tables.expr_ty(expr)); match ty.sty { - ty::TyDynamic(..) => { - cx.tcx - .associated_items(ty.ty_to_def_id().expect("trait impl not found")) - .any(|item| is_is_empty(cx, &item)) - }, - ty::TyProjection(_) => { - ty.ty_to_def_id().map_or( - false, - |id| has_is_empty_impl(cx, id), - ) - }, + ty::TyDynamic(..) => cx.tcx + .associated_items(ty.ty_to_def_id().expect("trait impl not found")) + .any(|item| is_is_empty(cx, &item)), + ty::TyProjection(_) => ty.ty_to_def_id() + .map_or(false, |id| has_is_empty_impl(cx, id)), ty::TyAdt(id, _) => has_is_empty_impl(cx, id.did), ty::TyArray(..) | ty::TySlice(..) | ty::TyStr => true, _ => false, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 95d45bed1337..41ca62b470c5 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -8,39 +8,42 @@ #![feature(slice_patterns)] #![feature(stmt_expr_attributes)] #![feature(conservative_impl_trait)] - #![allow(unknown_lints, indexing_slicing, shadow_reuse, missing_docs_in_private_items)] -extern crate syntax; -extern crate syntax_pos; #[macro_use] extern crate rustc; +extern crate syntax; +extern crate syntax_pos; extern crate toml; // for unicode nfc normalization + extern crate unicode_normalization; // for semver check in attrs.rs + extern crate semver; // for regex checking + extern crate regex_syntax; // for finding minimal boolean expressions + extern crate quine_mc_cluskey; -extern crate rustc_errors; -extern crate rustc_plugin; extern crate rustc_const_eval; extern crate rustc_const_math; +extern crate rustc_errors; +extern crate rustc_plugin; #[macro_use] extern crate matches as matches_macro; +extern crate serde; #[macro_use] extern crate serde_derive; -extern crate serde; #[macro_use] extern crate lazy_static; diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 4cb386471c9c..9e7e19a8df5a 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -2,10 +2,10 @@ use reexport::*; use rustc::lint::*; use rustc::hir::def::Def; use rustc::hir::*; -use rustc::hir::intravisit::{Visitor, walk_ty, walk_ty_param_bound, walk_fn_decl, walk_generics, NestedVisitorMap}; -use std::collections::{HashSet, HashMap}; +use rustc::hir::intravisit::{walk_fn_decl, walk_generics, walk_ty, walk_ty_param_bound, NestedVisitorMap, Visitor}; +use std::collections::{HashMap, HashSet}; use syntax::codemap::Span; -use utils::{in_external_macro, span_lint, last_path_segment}; +use utils::{in_external_macro, last_path_segment, span_lint}; use syntax::symbol::keywords; /// **What it does:** Checks for lifetime annotations which can be removed by @@ -171,7 +171,9 @@ fn could_use_elision<'a, 'tcx: 'a>( }; if let Some(body_id) = body { - let mut checker = BodyLifetimeChecker { lifetimes_used_in_body: false }; + let mut checker = BodyLifetimeChecker { + lifetimes_used_in_body: false, + }; checker.visit_expr(&cx.tcx.hir.body(body_id).value); if checker.lifetimes_used_in_body { return false; @@ -192,9 +194,9 @@ fn could_use_elision<'a, 'tcx: 'a>( // no output lifetimes, check distinctness of input lifetimes // only unnamed and static, ok - let unnamed_and_static = input_lts.iter().all(|lt| { - *lt == RefLt::Unnamed || *lt == RefLt::Static - }); + let unnamed_and_static = input_lts + .iter() + .all(|lt| *lt == RefLt::Unnamed || *lt == RefLt::Static); if unnamed_and_static { return false; } @@ -210,8 +212,8 @@ fn could_use_elision<'a, 'tcx: 'a>( match (&input_lts[0], &output_lts[0]) { (&RefLt::Named(n1), &RefLt::Named(n2)) if n1 == n2 => true, (&RefLt::Named(_), &RefLt::Unnamed) => true, - _ => false, // already elided, different named lifetimes - // or something static going on + _ => false, /* already elided, different named lifetimes + * or something static going on */ } } else { false @@ -277,7 +279,11 @@ impl<'v, 't> RefVisitor<'v, 't> { } fn into_vec(self) -> Option> { - if self.abort { None } else { Some(self.lts) } + if self.abort { + None + } else { + Some(self.lts) + } } fn collect_anonymous_lifetimes(&mut self, qpath: &QPath, ty: &Ty) { @@ -285,8 +291,7 @@ impl<'v, 't> RefVisitor<'v, 't> { if !last_path_segment.parenthesized && last_path_segment.lifetimes.is_empty() { let hir_id = self.cx.tcx.hir.node_to_hir_id(ty.id); match self.cx.tables.qpath_def(qpath, hir_id) { - Def::TyAlias(def_id) | - Def::Struct(def_id) => { + Def::TyAlias(def_id) | Def::Struct(def_id) => { let generics = self.cx.tcx.generics_of(def_id); for _ in generics.regions.as_slice() { self.record(&None); @@ -318,11 +323,9 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> { TyPath(ref path) => { self.collect_anonymous_lifetimes(path, ty); }, - TyImplTrait(ref param_bounds) => { - for bound in param_bounds { - if let RegionTyParamBound(_) = *bound { - self.record(&None); - } + TyImplTrait(ref param_bounds) => for bound in param_bounds { + if let RegionTyParamBound(_) = *bound { + self.record(&None); } }, TyTraitObject(ref bounds, ref lt) => { @@ -366,11 +369,9 @@ fn has_where_lifetimes<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, where_clause: & // and check that all lifetimes are allowed match visitor.into_vec() { None => return false, - Some(lts) => { - for lt in lts { - if !allowed_lts.contains(<) { - return true; - } + Some(lts) => for lt in lts { + if !allowed_lts.contains(<) { + return true; } }, } diff --git a/clippy_lints/src/literal_digit_grouping.rs b/clippy_lints/src/literal_digit_grouping.rs index dbb1a7a9b867..1cd539eac398 100644 --- a/clippy_lints/src/literal_digit_grouping.rs +++ b/clippy_lints/src/literal_digit_grouping.rs @@ -4,7 +4,7 @@ use rustc::lint::*; use syntax::ast::*; use syntax_pos; -use utils::{span_help_and_lint, snippet_opt, in_external_macro}; +use utils::{in_external_macro, snippet_opt, span_help_and_lint}; /// **What it does:** Warns if a long integral or floating-point constant does /// not contain underscores. @@ -195,33 +195,27 @@ enum WarningType { impl WarningType { pub fn display(&self, grouping_hint: &str, cx: &EarlyContext, span: &syntax_pos::Span) { match *self { - WarningType::UnreadableLiteral => { - span_help_and_lint( - cx, - UNREADABLE_LITERAL, - *span, - "long literal lacking separators", - &format!("consider: {}", grouping_hint), - ) - }, - WarningType::LargeDigitGroups => { - span_help_and_lint( - cx, - LARGE_DIGIT_GROUPS, - *span, - "digit groups should be smaller", - &format!("consider: {}", grouping_hint), - ) - }, - WarningType::InconsistentDigitGrouping => { - span_help_and_lint( - cx, - INCONSISTENT_DIGIT_GROUPING, - *span, - "digits grouped inconsistently by underscores", - &format!("consider: {}", grouping_hint), - ) - }, + WarningType::UnreadableLiteral => span_help_and_lint( + cx, + UNREADABLE_LITERAL, + *span, + "long literal lacking separators", + &format!("consider: {}", grouping_hint), + ), + WarningType::LargeDigitGroups => span_help_and_lint( + cx, + LARGE_DIGIT_GROUPS, + *span, + "digit groups should be smaller", + &format!("consider: {}", grouping_hint), + ), + WarningType::InconsistentDigitGrouping => span_help_and_lint( + cx, + INCONSISTENT_DIGIT_GROUPING, + *span, + "digits grouped inconsistently by underscores", + &format!("consider: {}", grouping_hint), + ), }; } } diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 7a5f7b492785..2f87fe0f3963 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -2,7 +2,7 @@ use reexport::*; use rustc::hir::*; use rustc::hir::def::Def; use rustc::hir::def_id::DefId; -use rustc::hir::intravisit::{Visitor, walk_expr, walk_block, walk_decl, walk_pat, walk_stmt, NestedVisitorMap}; +use rustc::hir::intravisit::{walk_block, walk_decl, walk_expr, walk_pat, walk_stmt, NestedVisitorMap, Visitor}; use rustc::hir::map::Node::{NodeBlock, NodeExpr, NodeStmt}; use rustc::lint::*; use rustc::middle::const_val::ConstVal; @@ -14,9 +14,9 @@ use std::collections::{HashMap, HashSet}; use syntax::ast; use utils::sugg; -use utils::{snippet, span_lint, get_parent_expr, match_trait_method, match_type, multispan_sugg, in_external_macro, - is_refutable, span_help_and_lint, is_integer_literal, get_enclosing_block, span_lint_and_then, higher, - last_path_segment, span_lint_and_sugg}; +use utils::{get_enclosing_block, get_parent_expr, higher, in_external_macro, is_integer_literal, is_refutable, + last_path_segment, match_trait_method, match_type, multispan_sugg, snippet, span_help_and_lint, span_lint, + span_lint_and_sugg, span_lint_and_then}; use utils::paths; /// **What it does:** Checks for looping over the range of `0..len` of some @@ -340,11 +340,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { // check for never_loop match expr.node { - ExprWhile(_, ref block, _) | - ExprLoop(ref block, _, _) => { - if never_loop(block, &expr.id) { - span_lint(cx, NEVER_LOOP, expr.span, "this loop never actually loops"); - } + ExprWhile(_, ref block, _) | ExprLoop(ref block, _, _) => if never_loop(block, &expr.id) { + span_lint(cx, NEVER_LOOP, expr.span, "this loop never actually loops"); }, _ => (), } @@ -360,7 +357,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { EMPTY_LOOP, expr.span, "empty `loop {}` detected. You may want to either use `panic!()` or add \ - `std::thread::sleep(..);` to the loop body.", + `std::thread::sleep(..);` to the loop body.", ); } @@ -371,8 +368,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if let ExprMatch(ref matchexpr, ref arms, ref source) = inner.node { // ensure "if let" compatible match structure match *source { - MatchSource::Normal | - MatchSource::IfLetDesugar { .. } => { + MatchSource::Normal | MatchSource::IfLetDesugar { .. } => { if arms.len() == 2 && arms[0].pats.len() == 1 && arms[0].guard.is_none() && arms[1].pats.len() == 1 && arms[1].guard.is_none() && is_break_expr(&arms[1].body) @@ -407,8 +403,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } if let ExprMatch(ref match_expr, ref arms, MatchSource::WhileLetDesugar) = expr.node { let pat = &arms[0].pats[0].node; - if let (&PatKind::TupleStruct(ref qpath, ref pat_args, _), - &ExprMethodCall(ref method_path, _, ref method_args)) = (pat, &match_expr.node) + if let ( + &PatKind::TupleStruct(ref qpath, ref pat_args, _), + &ExprMethodCall(ref method_path, _, ref method_args), + ) = (pat, &match_expr.node) { let iter_expr = &method_args[0]; let lhs_constructor = last_path_segment(qpath); @@ -441,7 +439,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { UNUSED_COLLECT, expr.span, "you are collect()ing an iterator and throwing away the result. \ - Consider using an explicit for loop to exhaust the iterator", + Consider using an explicit for loop to exhaust the iterator", ); } } @@ -455,28 +453,25 @@ fn never_loop(block: &Block, id: &NodeId) -> bool { fn contains_continue_block(block: &Block, dest: &NodeId) -> bool { block.stmts.iter().any(|e| contains_continue_stmt(e, dest)) || - block.expr.as_ref().map_or( - false, - |e| contains_continue_expr(e, dest), - ) + block + .expr + .as_ref() + .map_or(false, |e| contains_continue_expr(e, dest)) } fn contains_continue_stmt(stmt: &Stmt, dest: &NodeId) -> bool { match stmt.node { - StmtSemi(ref e, _) | - StmtExpr(ref e, _) => contains_continue_expr(e, dest), + StmtSemi(ref e, _) | StmtExpr(ref e, _) => contains_continue_expr(e, dest), StmtDecl(ref d, _) => contains_continue_decl(d, dest), } } fn contains_continue_decl(decl: &Decl, dest: &NodeId) -> bool { match decl.node { - DeclLocal(ref local) => { - local.init.as_ref().map_or( - false, - |e| contains_continue_expr(e, dest), - ) - }, + DeclLocal(ref local) => local + .init + .as_ref() + .map_or(false, |e| contains_continue_expr(e, dest)), _ => false, } } @@ -492,9 +487,9 @@ fn contains_continue_expr(expr: &Expr, dest: &NodeId) -> bool { ExprTupField(ref e, _) | ExprAddrOf(_, ref e) | ExprRepeat(ref e, _) => contains_continue_expr(e, dest), - ExprArray(ref es) | - ExprMethodCall(_, _, ref es) | - ExprTup(ref es) => es.iter().any(|e| contains_continue_expr(e, dest)), + ExprArray(ref es) | ExprMethodCall(_, _, ref es) | ExprTup(ref es) => { + es.iter().any(|e| contains_continue_expr(e, dest)) + }, ExprCall(ref e, ref es) => { contains_continue_expr(e, dest) || es.iter().any(|e| contains_continue_expr(e, dest)) }, @@ -502,22 +497,17 @@ fn contains_continue_expr(expr: &Expr, dest: &NodeId) -> bool { ExprAssign(ref e1, ref e2) | ExprAssignOp(_, ref e1, ref e2) | ExprIndex(ref e1, ref e2) => [e1, e2].iter().any(|e| contains_continue_expr(e, dest)), - ExprIf(ref e, ref e2, ref e3) => { - [e, e2].iter().chain(e3.as_ref().iter()).any(|e| { - contains_continue_expr(e, dest) - }) - }, + ExprIf(ref e, ref e2, ref e3) => [e, e2] + .iter() + .chain(e3.as_ref().iter()) + .any(|e| contains_continue_expr(e, dest)), ExprWhile(ref e, ref b, _) => contains_continue_expr(e, dest) || contains_continue_block(b, dest), ExprMatch(ref e, ref arms, _) => { contains_continue_expr(e, dest) || arms.iter().any(|a| contains_continue_expr(&a.body, dest)) }, ExprBlock(ref block) => contains_continue_block(block, dest), - ExprStruct(_, _, ref base) => { - base.as_ref().map_or( - false, - |e| contains_continue_expr(e, dest), - ) - }, + ExprStruct(_, _, ref base) => base.as_ref() + .map_or(false, |e| contains_continue_expr(e, dest)), ExprAgain(d) => d.target_id.opt_id().map_or(false, |id| id == *dest), _ => false, } @@ -529,8 +519,7 @@ fn loop_exit_block(block: &Block) -> bool { fn loop_exit_stmt(stmt: &Stmt) -> bool { match stmt.node { - StmtSemi(ref e, _) | - StmtExpr(ref e, _) => loop_exit_expr(e), + StmtSemi(ref e, _) | StmtExpr(ref e, _) => loop_exit_expr(e), StmtDecl(ref d, _) => loop_exit_decl(d), } } @@ -552,9 +541,7 @@ fn loop_exit_expr(expr: &Expr) -> bool { ExprTupField(ref e, _) | ExprAddrOf(_, ref e) | ExprRepeat(ref e, _) => loop_exit_expr(e), - ExprArray(ref es) | - ExprMethodCall(_, _, ref es) | - ExprTup(ref es) => es.iter().any(|e| loop_exit_expr(e)), + ExprArray(ref es) | ExprMethodCall(_, _, ref es) | ExprTup(ref es) => es.iter().any(|e| loop_exit_expr(e)), ExprCall(ref e, ref es) => loop_exit_expr(e) || es.iter().any(|e| loop_exit_expr(e)), ExprBinary(_, ref e1, ref e2) | ExprAssign(ref e1, ref e2) | @@ -595,10 +582,10 @@ fn check_for_loop_range<'a, 'tcx>( expr: &'tcx Expr, ) { if let Some(higher::Range { - start: Some(start), - ref end, - limits, - }) = higher::range(arg) + start: Some(start), + ref end, + limits, + }) = higher::range(arg) { // the var must be a single name if let PatKind::Binding(_, def_id, ref ident, _) = pat.node { @@ -613,9 +600,11 @@ fn check_for_loop_range<'a, 'tcx>( // linting condition: we only indexed one variable if visitor.indexed.len() == 1 { - let (indexed, indexed_extent) = visitor.indexed.into_iter().next().expect( - "already checked that we have exactly 1 element", - ); + let (indexed, indexed_extent) = visitor + .indexed + .into_iter() + .next() + .expect("already checked that we have exactly 1 element"); // ensure that the indexed variable was declared before the loop, see #601 if let Some(indexed_extent) = indexed_extent { @@ -659,16 +648,22 @@ fn check_for_loop_range<'a, 'tcx>( }; if visitor.nonindex { - span_lint_and_then(cx, - NEEDLESS_RANGE_LOOP, - expr.span, - &format!("the loop variable `{}` is used to index `{}`", ident.node, indexed), - |db| { - multispan_sugg(db, - "consider using an iterator".to_string(), - vec![(pat.span, format!("({}, )", ident.node)), - (arg.span, format!("{}.iter().enumerate(){}{}", indexed, take, skip))]); - }); + span_lint_and_then( + cx, + NEEDLESS_RANGE_LOOP, + expr.span, + &format!("the loop variable `{}` is used to index `{}`", ident.node, indexed), + |db| { + multispan_sugg( + db, + "consider using an iterator".to_string(), + vec![ + (pat.span, format!("({}, )", ident.node)), + (arg.span, format!("{}.iter().enumerate(){}{}", indexed, take, skip)), + ], + ); + }, + ); } else { let repl = if starts_at_zero && take.is_empty() { format!("&{}", indexed) @@ -676,17 +671,19 @@ fn check_for_loop_range<'a, 'tcx>( format!("{}.iter(){}{}", indexed, take, skip) }; - span_lint_and_then(cx, - NEEDLESS_RANGE_LOOP, - expr.span, - &format!("the loop variable `{}` is only used to index `{}`.", - ident.node, - indexed), - |db| { - multispan_sugg(db, - "consider using an iterator".to_string(), - vec![(pat.span, "".to_string()), (arg.span, repl)]); - }); + span_lint_and_then( + cx, + NEEDLESS_RANGE_LOOP, + expr.span, + &format!("the loop variable `{}` is only used to index `{}`.", ident.node, indexed), + |db| { + multispan_sugg( + db, + "consider using an iterator".to_string(), + vec![(pat.span, "".to_string()), (arg.span, repl)], + ); + }, + ); } } } @@ -711,10 +708,10 @@ fn is_len_call(expr: &Expr, var: &Name) -> bool { fn check_for_loop_reverse_range(cx: &LateContext, arg: &Expr, expr: &Expr) { // if this for loop is iterating over a two-sided range... if let Some(higher::Range { - start: Some(start), - end: Some(end), - limits, - }) = higher::range(arg) + start: Some(start), + end: Some(end), + limits, + }) = higher::range(arg) { // ...and both sides are compile-time constant integers... let parent_item = cx.tcx.hir.get_parent(arg.id); @@ -743,19 +740,25 @@ fn check_for_loop_reverse_range(cx: &LateContext, arg: &Expr, expr: &Expr) { ".." }; - span_lint_and_then(cx, - REVERSE_RANGE_LOOP, - expr.span, - "this range is empty so this for loop will never run", - |db| { - db.span_suggestion(arg.span, - "consider using the following if you are attempting to iterate over this \ - range in reverse", - format!("({end}{dots}{start}).rev()", - end = end_snippet, - dots = dots, - start = start_snippet)); - }); + span_lint_and_then( + cx, + REVERSE_RANGE_LOOP, + expr.span, + "this range is empty so this for loop will never run", + |db| { + db.span_suggestion( + arg.span, + "consider using the following if you are attempting to iterate over this \ + range in reverse", + format!( + "({end}{dots}{start}).rev()", + end = end_snippet, + dots = dots, + start = start_snippet + ), + ); + }, + ); } else if eq && limits != ast::RangeLimits::Closed { // if they are equal, it's also problematic - this loop // will never run. @@ -783,7 +786,7 @@ fn lint_iter_method(cx: &LateContext, args: &[Expr], arg: &Expr, method_name: &s EXPLICIT_ITER_LOOP, arg.span, "it is more idiomatic to loop over references to containers instead of using explicit \ - iteration methods", + iteration methods", "to write this more concisely, try", format!("&{}{}", muta, object), ) @@ -816,7 +819,7 @@ fn check_for_loop_arg(cx: &LateContext, pat: &Pat, arg: &Expr, expr: &Expr) { EXPLICIT_INTO_ITER_LOOP, arg.span, "it is more idiomatic to loop over containers instead of using explicit \ - iteration methods`", + iteration methods`", "to write this more concisely, try", object.to_string(), ); @@ -827,7 +830,7 @@ fn check_for_loop_arg(cx: &LateContext, pat: &Pat, arg: &Expr, expr: &Expr) { ITER_NEXT_LOOP, expr.span, "you are iterating over `Iterator::next()` which is an Option; this will compile but is \ - probably not what you want", + probably not what you want", ); next_loop_linted = true; } @@ -848,7 +851,7 @@ fn check_arg_type(cx: &LateContext, pat: &Pat, arg: &Expr) { arg.span, &format!( "for loop over `{0}`, which is an `Option`. This is more readably written as an \ - `if let` statement.", + `if let` statement.", snippet(cx, arg.span, "_") ), &format!( @@ -864,7 +867,7 @@ fn check_arg_type(cx: &LateContext, pat: &Pat, arg: &Expr) { arg.span, &format!( "for loop over `{0}`, which is a `Result`. This is more readably written as an \ - `if let` statement.", + `if let` statement.", snippet(cx, arg.span, "_") ), &format!( @@ -894,14 +897,14 @@ fn check_for_loop_explicit_counter<'a, 'tcx>( // For each candidate, check the parent block to see if // it's initialized to zero at the start of the loop. let map = &cx.tcx.hir; - let parent_scope = map.get_enclosing_scope(expr.id).and_then(|id| { - map.get_enclosing_scope(id) - }); + let parent_scope = map.get_enclosing_scope(expr.id) + .and_then(|id| map.get_enclosing_scope(id)); if let Some(parent_id) = parent_scope { if let NodeBlock(block) = map.get(parent_id) { - for (id, _) in visitor.states.iter().filter( - |&(_, v)| *v == VarState::IncrOnce, - ) + for (id, _) in visitor + .states + .iter() + .filter(|&(_, v)| *v == VarState::IncrOnce) { let mut visitor2 = InitializeVisitor { cx: cx, @@ -922,7 +925,7 @@ fn check_for_loop_explicit_counter<'a, 'tcx>( expr.span, &format!( "the variable `{0}` is used as a loop counter. Consider using `for ({0}, \ - item) in {1}.enumerate()` or similar iterators", + item) in {1}.enumerate()` or similar iterators", name, snippet(cx, arg.span, "_") ), @@ -948,12 +951,10 @@ fn check_for_loop_over_map_kv<'a, 'tcx>( if pat.len() == 2 { let arg_span = arg.span; let (new_pat_span, kind, ty, mutbl) = match cx.tables.expr_ty(arg).sty { - ty::TyRef(_, ref tam) => { - match (&pat[0].node, &pat[1].node) { - (key, _) if pat_is_wild(key, body) => (pat[1].span, "value", tam.ty, tam.mutbl), - (_, value) if pat_is_wild(value, body) => (pat[0].span, "key", tam.ty, MutImmutable), - _ => return, - } + ty::TyRef(_, ref tam) => match (&pat[0].node, &pat[1].node) { + (key, _) if pat_is_wild(key, body) => (pat[1].span, "value", tam.ty, tam.mutbl), + (_, value) if pat_is_wild(value, body) => (pat[0].span, "key", tam.ty, MutImmutable), + _ => return, }, _ => return, }; @@ -967,21 +968,26 @@ fn check_for_loop_over_map_kv<'a, 'tcx>( }; if match_type(cx, ty, &paths::HASHMAP) || match_type(cx, ty, &paths::BTREEMAP) { - span_lint_and_then(cx, - FOR_KV_MAP, - expr.span, - &format!("you seem to want to iterate on a map's {}s", kind), - |db| { - let map = sugg::Sugg::hir(cx, arg, "map"); - multispan_sugg(db, - "use the corresponding method".into(), - vec![(pat_span, snippet(cx, new_pat_span, kind).into_owned()), - (arg_span, format!("{}.{}s{}()", map.maybe_par(), kind, mutbl))]); - }); + span_lint_and_then( + cx, + FOR_KV_MAP, + expr.span, + &format!("you seem to want to iterate on a map's {}s", kind), + |db| { + let map = sugg::Sugg::hir(cx, arg, "map"); + multispan_sugg( + db, + "use the corresponding method".into(), + vec![ + (pat_span, snippet(cx, new_pat_span, kind).into_owned()), + (arg_span, format!("{}.{}s{}()", map.maybe_par(), kind, mutbl)), + ], + ); + }, + ); } } } - } /// Return true if the pattern is a `PatWild` or an ident prefixed with `'_'`. @@ -1011,7 +1017,7 @@ fn match_var(expr: &Expr, var: Name) -> bool { struct UsedVisitor { var: ast::Name, // var to look for - used: bool, // has the var been used otherwise? + used: bool, // has the var been used otherwise? } impl<'tcx> Visitor<'tcx> for UsedVisitor { @@ -1196,12 +1202,9 @@ fn extract_expr_from_first_stmt(block: &Block) -> Option<&Expr> { fn extract_first_expr(block: &Block) -> Option<&Expr> { match block.expr { Some(ref expr) if block.stmts.is_empty() => Some(expr), - None if !block.stmts.is_empty() => { - match block.stmts[0].node { - StmtExpr(ref expr, _) | - StmtSemi(ref expr, _) => Some(expr), - StmtDecl(..) => None, - } + None if !block.stmts.is_empty() => match block.stmts[0].node { + StmtExpr(ref expr, _) | StmtSemi(ref expr, _) => Some(expr), + StmtDecl(..) => None, }, _ => None, } @@ -1211,11 +1214,9 @@ fn extract_first_expr(block: &Block) -> Option<&Expr> { fn is_break_expr(expr: &Expr) -> bool { match expr.node { ExprBreak(dest, _) if dest.ident.is_none() => true, - ExprBlock(ref b) => { - match extract_first_expr(b) { - Some(subexpr) => is_break_expr(subexpr), - None => false, - } + ExprBlock(ref b) => match extract_first_expr(b) { + Some(subexpr) => is_break_expr(subexpr), + None => false, }, _ => false, } @@ -1226,7 +1227,7 @@ fn is_break_expr(expr: &Expr) -> bool { // at the start of the loop. #[derive(PartialEq)] enum VarState { - Initial, // Not examined yet + Initial, // Not examined yet IncrOnce, // Incremented exactly once, may be a loop counter Declared, // Declared but not (yet) initialized to zero Warn, @@ -1235,9 +1236,9 @@ enum VarState { /// Scan a for loop for variables that are incremented exactly once. struct IncrementVisitor<'a, 'tcx: 'a> { - cx: &'a LateContext<'a, 'tcx>, // context reference + cx: &'a LateContext<'a, 'tcx>, // context reference states: HashMap, // incremented variables - depth: u32, // depth of conditional expressions + depth: u32, // depth of conditional expressions done: bool, } @@ -1291,7 +1292,7 @@ impl<'a, 'tcx> Visitor<'tcx> for IncrementVisitor<'a, 'tcx> { /// Check whether a variable is initialized to zero at the start of a loop. struct InitializeVisitor<'a, 'tcx: 'a> { cx: &'a LateContext<'a, 'tcx>, // context reference - end_expr: &'tcx Expr, // the for loop. Stop scanning here. + end_expr: &'tcx Expr, // the for loop. Stop scanning here. var_id: NodeId, state: VarState, name: Option, @@ -1379,9 +1380,10 @@ fn var_def_id(cx: &LateContext, expr: &Expr) -> Option { if let ExprPath(ref qpath) = expr.node { let path_res = cx.tables.qpath_def(qpath, expr.hir_id); if let Def::Local(def_id) = path_res { - let node_id = cx.tcx.hir.as_local_node_id(def_id).expect( - "That DefId should be valid", - ); + let node_id = cx.tcx + .hir + .as_local_node_id(def_id) + .expect("That DefId should be valid"); return Some(node_id); } } @@ -1425,13 +1427,11 @@ fn is_loop_nested(cx: &LateContext, loop_expr: &Expr, iter_expr: &Expr) -> bool return false; } match cx.tcx.hir.find(parent) { - Some(NodeExpr(expr)) => { - match expr.node { - ExprLoop(..) | ExprWhile(..) => { - return true; - }, - _ => (), - } + Some(NodeExpr(expr)) => match expr.node { + ExprLoop(..) | ExprWhile(..) => { + return true; + }, + _ => (), }, Some(NodeBlock(block)) => { let mut block_visitor = LoopNestVisitor { @@ -1455,12 +1455,12 @@ fn is_loop_nested(cx: &LateContext, loop_expr: &Expr, iter_expr: &Expr) -> bool #[derive(PartialEq, Eq)] enum Nesting { - Unknown, // no nesting detected yet - RuledOut, // the iterator is initialized or assigned within scope + Unknown, // no nesting detected yet + RuledOut, // the iterator is initialized or assigned within scope LookFurther, // no nesting detected, no further walk required } -use self::Nesting::{Unknown, RuledOut, LookFurther}; +use self::Nesting::{LookFurther, RuledOut, Unknown}; struct LoopNestVisitor { id: NodeId, @@ -1486,11 +1486,8 @@ impl<'tcx> Visitor<'tcx> for LoopNestVisitor { return; } match expr.node { - ExprAssign(ref path, _) | - ExprAssignOp(_, ref path, _) => { - if match_var(path, self.iterator) { - self.nesting = RuledOut; - } + ExprAssign(ref path, _) | ExprAssignOp(_, ref path, _) => if match_var(path, self.iterator) { + self.nesting = RuledOut; }, _ => walk_expr(self, expr), } diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index f0e19a3b5777..733022f1703f 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -2,8 +2,8 @@ use rustc::lint::*; use rustc::hir::*; use rustc::ty; use syntax::ast; -use utils::{is_adjusted, match_qpath, match_trait_method, match_type, remove_blocks, paths, snippet, - span_help_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth, iter_input_pats}; +use utils::{is_adjusted, iter_input_pats, match_qpath, match_trait_method, match_type, paths, remove_blocks, snippet, + span_help_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth}; /// **What it does:** Checks for mapping `clone()` over an iterator. /// @@ -73,21 +73,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } }} }, - ExprPath(ref path) => { - if match_qpath(path, &paths::CLONE) { - let type_name = get_type_name(cx, expr, &args[0]).unwrap_or("_"); - span_help_and_lint( - cx, - MAP_CLONE, - expr.span, - &format!( - "you seem to be using .map() to clone the contents of an \ - {}, consider using `.cloned()`", - type_name - ), - &format!("try\n{}.cloned()", snippet(cx, args[0].span, "..")), - ); - } + ExprPath(ref path) => if match_qpath(path, &paths::CLONE) { + let type_name = get_type_name(cx, expr, &args[0]).unwrap_or("_"); + span_help_and_lint( + cx, + MAP_CLONE, + expr.span, + &format!( + "you seem to be using .map() to clone the contents of an \ + {}, consider using `.cloned()`", + type_name + ), + &format!("try\n{}.cloned()", snippet(cx, args[0].span, "..")), + ); }, _ => (), } diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 77050a0e2994..b9a4507c5d7e 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -11,8 +11,8 @@ use syntax::ast::LitKind; use syntax::ast::NodeId; use syntax::codemap::Span; use utils::paths; -use utils::{match_type, snippet, span_note_and_lint, span_lint_and_then, span_lint_and_sugg, in_external_macro, - expr_block, walk_ptrs_ty, is_expn_of, remove_blocks, is_allowed}; +use utils::{expr_block, in_external_macro, is_allowed, is_expn_of, match_type, remove_blocks, snippet, + span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty}; use utils::sugg::Sugg; /// **What it does:** Checks for matches with a single arm where an `if let` @@ -219,7 +219,7 @@ fn report_single_match_single_pattern(cx: &LateContext, ex: &Expr, arms: &[Arm], lint, expr.span, "you seem to be trying to use match for destructuring a single pattern. Consider using `if \ - let`", + let`", "try this", format!( "if let {} = {} {}{}", @@ -290,21 +290,17 @@ fn check_match_bool(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { if let Some((true_expr, false_expr)) = exprs { let sugg = match (is_unit_expr(true_expr), is_unit_expr(false_expr)) { - (false, false) => { - Some(format!( - "if {} {} else {}", - snippet(cx, ex.span, "b"), - expr_block(cx, true_expr, None, ".."), - expr_block(cx, false_expr, None, "..") - )) - }, - (false, true) => { - Some(format!( - "if {} {}", - snippet(cx, ex.span, "b"), - expr_block(cx, true_expr, None, "..") - )) - }, + (false, false) => Some(format!( + "if {} {} else {}", + snippet(cx, ex.span, "b"), + expr_block(cx, true_expr, None, ".."), + expr_block(cx, false_expr, None, "..") + )), + (false, true) => Some(format!( + "if {} {}", + snippet(cx, ex.span, "b"), + expr_block(cx, true_expr, None, "..") + )), (true, false) => { let test = Sugg::hir(cx, ex, ".."); Some(format!("if {} {}", !test, expr_block(cx, false_expr, None, ".."))) @@ -317,7 +313,6 @@ fn check_match_bool(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { } } } - }, ); } @@ -384,15 +379,17 @@ fn is_panic_block(block: &Block) -> bool { fn check_match_ref_pats(cx: &LateContext, ex: &Expr, arms: &[Arm], source: MatchSource, expr: &Expr) { if has_only_ref_pats(arms) { if let ExprAddrOf(Mutability::MutImmutable, ref inner) = ex.node { - span_lint_and_then(cx, - MATCH_REF_PATS, - expr.span, - "you don't need to add `&` to both the expression and the patterns", - |db| { - let inner = Sugg::hir(cx, inner, ".."); - let template = match_template(expr.span, source, &inner); - db.span_suggestion(expr.span, "try", template); - }); + span_lint_and_then( + cx, + MATCH_REF_PATS, + expr.span, + "you don't need to add `&` to both the expression and the patterns", + |db| { + let inner = Sugg::hir(cx, inner, ".."); + let template = match_template(expr.span, source, &inner); + db.span_suggestion(expr.span, "try", template); + }, + ); } else { span_lint_and_then( cx, @@ -471,24 +468,18 @@ fn type_ranges(ranges: &[SpannedRange]) -> TypedRanges { ranges .iter() .filter_map(|range| match range.node { - (ConstVal::Integral(start), Bound::Included(ConstVal::Integral(end))) => { - Some(SpannedRange { - span: range.span, - node: (start, Bound::Included(end)), - }) - }, - (ConstVal::Integral(start), Bound::Excluded(ConstVal::Integral(end))) => { - Some(SpannedRange { - span: range.span, - node: (start, Bound::Excluded(end)), - }) - }, - (ConstVal::Integral(start), Bound::Unbounded) => { - Some(SpannedRange { - span: range.span, - node: (start, Bound::Unbounded), - }) - }, + (ConstVal::Integral(start), Bound::Included(ConstVal::Integral(end))) => Some(SpannedRange { + span: range.span, + node: (start, Bound::Included(end)), + }), + (ConstVal::Integral(start), Bound::Excluded(ConstVal::Integral(end))) => Some(SpannedRange { + span: range.span, + node: (start, Bound::Excluded(end)), + }), + (ConstVal::Integral(start), Bound::Unbounded) => Some(SpannedRange { + span: range.span, + node: (start, Bound::Unbounded), + }), _ => None, }) .collect() @@ -507,9 +498,9 @@ fn has_only_ref_pats(arms: &[Arm]) -> bool { .flat_map(|a| &a.pats) .map(|p| { match p.node { - PatKind::Ref(..) => Some(true), // &-patterns + PatKind::Ref(..) => Some(true), // &-patterns PatKind::Wild => Some(false), // an "anything" wildcard is also fine - _ => None, // any other pattern is not fine + _ => None, // any other pattern is not fine } }) .collect::>>(); @@ -540,8 +531,7 @@ where impl<'a, T: Copy> Kind<'a, T> { fn range(&self) -> &'a SpannedRange { match *self { - Kind::Start(_, r) | - Kind::End(_, r) => r, + Kind::Start(_, r) | Kind::End(_, r) => r, } } @@ -562,22 +552,16 @@ where impl<'a, T: Copy + Ord> Ord for Kind<'a, T> { fn cmp(&self, other: &Self) -> Ordering { match (self.value(), other.value()) { - (Bound::Included(a), Bound::Included(b)) | - (Bound::Excluded(a), Bound::Excluded(b)) => a.cmp(&b), + (Bound::Included(a), Bound::Included(b)) | (Bound::Excluded(a), Bound::Excluded(b)) => a.cmp(&b), // Range patterns cannot be unbounded (yet) - (Bound::Unbounded, _) | - (_, Bound::Unbounded) => unimplemented!(), - (Bound::Included(a), Bound::Excluded(b)) => { - match a.cmp(&b) { - Ordering::Equal => Ordering::Greater, - other => other, - } + (Bound::Unbounded, _) | (_, Bound::Unbounded) => unimplemented!(), + (Bound::Included(a), Bound::Excluded(b)) => match a.cmp(&b) { + Ordering::Equal => Ordering::Greater, + other => other, }, - (Bound::Excluded(a), Bound::Included(b)) => { - match a.cmp(&b) { - Ordering::Equal => Ordering::Less, - other => other, - } + (Bound::Excluded(a), Bound::Included(b)) => match a.cmp(&b) { + Ordering::Equal => Ordering::Less, + other => other, }, } } @@ -594,10 +578,8 @@ where for (a, b) in values.iter().zip(values.iter().skip(1)) { match (a, b) { - (&Kind::Start(_, ra), &Kind::End(_, rb)) => { - if ra.node != rb.node { - return Some((ra, rb)); - } + (&Kind::Start(_, ra), &Kind::End(_, rb)) => if ra.node != rb.node { + return Some((ra, rb)); }, (&Kind::End(a, _), &Kind::Start(b, _)) if a != Bound::Included(b) => (), _ => return Some((a.range(), b.range())), diff --git a/clippy_lints/src/mem_forget.rs b/clippy_lints/src/mem_forget.rs index edf477720d58..9058d0d102da 100644 --- a/clippy_lints/src/mem_forget.rs +++ b/clippy_lints/src/mem_forget.rs @@ -39,8 +39,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MemForget { if match forgot_ty.ty_adt_def() { Some(def) => def.has_dtor(cx.tcx), _ => false, - } - { + } { span_lint(cx, MEM_FORGET, e.span, "usage of mem::forget on Drop type"); } } diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index cfaa9f698e0a..84c213023a2d 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -8,10 +8,10 @@ use rustc_const_eval::ConstContext; use std::borrow::Cow; use std::fmt; use syntax::codemap::Span; -use utils::{get_trait_def_id, implements_trait, in_external_macro, in_macro, is_copy, match_qpath, match_trait_method, - match_type, method_chain_args, return_ty, same_tys, snippet, span_lint, span_lint_and_then, - span_lint_and_sugg, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth, last_path_segment, - single_segment_path, match_def_path, is_self, is_self_ty, iter_input_pats, match_path}; +use utils::{get_trait_def_id, implements_trait, in_external_macro, in_macro, is_copy, is_self, is_self_ty, + iter_input_pats, last_path_segment, match_def_path, match_path, match_qpath, match_trait_method, + match_type, method_chain_args, return_ty, same_tys, single_segment_path, snippet, span_lint, + span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth}; use utils::paths; use utils::sugg; @@ -618,11 +618,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } match self_ty.sty { - ty::TyRef(_, ty) if ty.ty.sty == ty::TyStr => { - for &(method, pos) in &PATTERN_METHODS { - if method_call.name == method && args.len() > pos { - lint_single_char_pattern(cx, expr, &args[pos]); - } + ty::TyRef(_, ty) if ty.ty.sty == ty::TyStr => for &(method, pos) in &PATTERN_METHODS { + if method_call.name == method && args.len() > pos { + lint_single_char_pattern(cx, expr, &args[pos]); } }, _ => (), @@ -723,12 +721,11 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[hir: if ["default", "new"].contains(&path) { let arg_ty = cx.tables.expr_ty(arg); - let default_trait_id = - if let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT) { - default_trait_id - } else { - return false; - }; + let default_trait_id = if let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT) { + default_trait_id + } else { + return false; + }; if implements_trait(cx, arg_ty, default_trait_id, &[]) { span_lint_and_sugg( @@ -771,13 +768,12 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[hir: } // (path, fn_has_argument, methods, suffix) - let know_types: &[(&[_], _, &[_], _)] = - &[ - (&paths::BTREEMAP_ENTRY, false, &["or_insert"], "with"), - (&paths::HASHMAP_ENTRY, false, &["or_insert"], "with"), - (&paths::OPTION, false, &["map_or", "ok_or", "or", "unwrap_or"], "else"), - (&paths::RESULT, true, &["or", "unwrap_or"], "else"), - ]; + let know_types: &[(&[_], _, &[_], _)] = &[ + (&paths::BTREEMAP_ENTRY, false, &["or_insert"], "with"), + (&paths::HASHMAP_ENTRY, false, &["or_insert"], "with"), + (&paths::OPTION, false, &["map_or", "ok_or", "or", "unwrap_or"], "else"), + (&paths::RESULT, true, &["or", "unwrap_or"], "else"), + ]; let self_ty = cx.tables.expr_ty(self_expr); @@ -835,7 +831,7 @@ fn lint_clone_on_copy(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr, arg_t CLONE_DOUBLE_REF, expr.span, "using `clone` on a double-reference; \ - this will copy the reference instead of cloning the inner type", + this will copy the reference instead of cloning the inner type", |db| if let Some(snip) = sugg::Sugg::hir_opt(cx, arg) { db.span_suggestion(expr.span, "try dereferencing it", format!("({}).clone()", snip.deref())); }, @@ -919,7 +915,7 @@ fn lint_iter_cloned_collect(cx: &LateContext, expr: &hir::Expr, iter_args: &[hir ITER_CLONED_COLLECT, expr.span, "called `cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and \ - more readable", + more readable", ); } } @@ -1021,12 +1017,10 @@ fn derefs_to_slice(cx: &LateContext, expr: &hir::Expr, ty: Ty) -> Option sugg::Sugg::hir_opt(cx, expr), ty::TyAdt(def, _) if def.is_box() && may_slice(cx, ty.boxed_ty()) => sugg::Sugg::hir_opt(cx, expr), - ty::TyRef(_, ty::TypeAndMut { ty: inner, .. }) => { - if may_slice(cx, inner) { - sugg::Sugg::hir_opt(cx, expr) - } else { - None - } + ty::TyRef(_, ty::TypeAndMut { ty: inner, .. }) => if may_slice(cx, inner) { + sugg::Sugg::hir_opt(cx, expr) + } else { + None }, _ => None, } @@ -1052,8 +1046,8 @@ fn lint_unwrap(cx: &LateContext, expr: &hir::Expr, unwrap_args: &[hir::Expr]) { expr.span, &format!( "used unwrap() on {} value. If you don't want to handle the {} case gracefully, consider \ - using expect() to provide a better panic \ - message", + using expect() to provide a better panic \ + message", kind, none_value ), @@ -1222,7 +1216,7 @@ fn lint_search_is_some( if match_trait_method(cx, &is_some_args[0], &paths::ITERATOR) { let msg = format!( "called `is_some()` after searching an `Iterator` with {}. This is more succinctly \ - expressed by calling `any()`.", + expressed by calling `any()`.", search_method ); let search_snippet = snippet(cx, search_args[1].span, ".."); @@ -1459,35 +1453,37 @@ fn is_as_ref_or_mut_trait(ty: &hir::Ty, self_ty: &hir::Ty, generics: &hir::Gener single_segment_ty(ty).map_or(false, |seg| { generics.ty_params.iter().any(|param| { param.name == seg.name && - param.bounds.iter().any(|bound| { - if let hir::TyParamBound::TraitTyParamBound(ref ptr, ..) = *bound { + param + .bounds + .iter() + .any(|bound| if let hir::TyParamBound::TraitTyParamBound(ref ptr, ..) = *bound { let path = &ptr.trait_ref.path; match_path(path, name) && - path.segments.last().map_or( - false, - |s| if s.parameters.parenthesized { + path.segments + .last() + .map_or(false, |s| if s.parameters.parenthesized { false } else { s.parameters.types.len() == 1 && (is_self_ty(&s.parameters.types[0]) || is_ty(&*s.parameters.types[0], self_ty)) - }, - ) + }) } else { false - } - }) + }) }) }) } fn is_ty(ty: &hir::Ty, self_ty: &hir::Ty) -> bool { match (&ty.node, &self_ty.node) { - (&hir::TyPath(hir::QPath::Resolved(_, ref ty_path)), - &hir::TyPath(hir::QPath::Resolved(_, ref self_ty_path))) => { - ty_path.segments.iter().map(|seg| seg.name).eq( - self_ty_path.segments.iter().map(|seg| seg.name), - ) - }, + ( + &hir::TyPath(hir::QPath::Resolved(_, ref ty_path)), + &hir::TyPath(hir::QPath::Resolved(_, ref self_ty_path)), + ) => ty_path + .segments + .iter() + .map(|seg| seg.name) + .eq(self_ty_path.segments.iter().map(|seg| seg.name)), _ => false, } } diff --git a/clippy_lints/src/minmax.rs b/clippy_lints/src/minmax.rs index a86b2b300e57..aea92311763b 100644 --- a/clippy_lints/src/minmax.rs +++ b/clippy_lints/src/minmax.rs @@ -1,7 +1,7 @@ -use consts::{Constant, constant_simple}; +use consts::{constant_simple, Constant}; use rustc::lint::*; use rustc::hir::*; -use std::cmp::{PartialOrd, Ordering}; +use std::cmp::{Ordering, PartialOrd}; use utils::{match_def_path, paths, span_lint}; /// **What it does:** Checks for expressions where `std::cmp::min` and `max` are @@ -41,9 +41,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MinMaxPass { return; } match (outer_max, outer_c.partial_cmp(&inner_c)) { - (_, None) | - (MinMax::Max, Some(Ordering::Less)) | - (MinMax::Min, Some(Ordering::Greater)) => (), + (_, None) | (MinMax::Max, Some(Ordering::Less)) | (MinMax::Min, Some(Ordering::Greater)) => (), _ => { span_lint(cx, MIN_MAX, expr.span, "this min/max combination leads to constant result"); }, diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index e7c3fb895fbd..da6919da93d7 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -7,12 +7,12 @@ use rustc::ty; use rustc::ty::subst::Substs; use rustc_const_eval::ConstContext; use rustc_const_math::ConstFloat; -use syntax::codemap::{Span, ExpnFormat}; -use utils::{get_item_name, get_parent_expr, implements_trait, in_macro, is_integer_literal, match_qpath, snippet, - span_lint, span_lint_and_then, walk_ptrs_ty, last_path_segment, iter_input_pats, in_constant, - match_trait_method, paths}; +use syntax::codemap::{ExpnFormat, Span}; +use 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}; use utils::sugg::Sugg; -use syntax::ast::{LitKind, CRATE_NODE_ID, FloatTy}; +use syntax::ast::{FloatTy, LitKind, CRATE_NODE_ID}; /// **What it does:** Checks for function arguments and let bindings denoted as /// `ref`. @@ -242,7 +242,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { TOPLEVEL_REF_ARG, arg.pat.span, "`ref` directly on a function argument is ignored. Consider using a reference type \ - instead.", + instead.", ); }, _ => {}, @@ -385,7 +385,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { expr.span, &format!( "used binding `{}` which is prefixed with an underscore. A leading \ - underscore signals that a binding will not be used.", + underscore signals that a binding will not be used.", binding ), ); @@ -484,16 +484,14 @@ fn check_to_owned(cx: &LateContext, expr: &Expr, other: &Expr) { return; } }, - ExprCall(ref path, ref v) if v.len() == 1 => { - if let ExprPath(ref path) = path.node { - if match_qpath(path, &["String", "from_str"]) || match_qpath(path, &["String", "from"]) { - (cx.tables.expr_ty_adjusted(&v[0]), snippet(cx, v[0].span, "..")) - } else { - return; - } + ExprCall(ref path, ref v) if v.len() == 1 => if let ExprPath(ref path) = path.node { + if match_qpath(path, &["String", "from_str"]) || match_qpath(path, &["String", "from"]) { + (cx.tables.expr_ty_adjusted(&v[0]), snippet(cx, v[0].span, "..")) } else { return; } + } else { + return; }, _ => return, }; @@ -554,8 +552,7 @@ fn check_to_owned(cx: &LateContext, expr: &Expr, other: &Expr) { fn is_used(cx: &LateContext, expr: &Expr) -> bool { if let Some(parent) = get_parent_expr(cx, expr) { match parent.node { - ExprAssign(_, ref rhs) | - ExprAssignOp(_, _, ref rhs) => **rhs == *expr, + ExprAssign(_, ref rhs) | ExprAssignOp(_, _, ref rhs) => **rhs == *expr, _ => is_used(cx, parent), } } else { @@ -567,20 +564,21 @@ fn is_used(cx: &LateContext, expr: &Expr) -> bool { /// generated by /// `#[derive(...)`] or the like). fn in_attributes_expansion(expr: &Expr) -> bool { - expr.span.ctxt().outer().expn_info().map_or( - false, - |info| matches!(info.callee.format, ExpnFormat::MacroAttribute(_)), - ) + expr.span + .ctxt() + .outer() + .expn_info() + .map_or(false, |info| matches!(info.callee.format, ExpnFormat::MacroAttribute(_))) } /// Test whether `def` is a variable defined outside a macro. fn non_macro_local(cx: &LateContext, def: &def::Def) -> bool { match *def { - def::Def::Local(def_id) | - def::Def::Upvar(def_id, _, _) => { - let id = cx.tcx.hir.as_local_node_id(def_id).expect( - "local variables should be found in the same crate", - ); + def::Def::Local(def_id) | def::Def::Upvar(def_id, _, _) => { + let id = cx.tcx + .hir + .as_local_node_id(def_id) + .expect("local variables should be found in the same crate"); !in_macro(cx.tcx.hir.span(id)) }, _ => false, diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index 52a97024e448..bf4df6e28730 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -4,7 +4,7 @@ use std::char; use syntax::ast::*; use syntax::codemap::Span; use syntax::visit::FnKind; -use utils::{constants, span_lint, span_help_and_lint, snippet, snippet_opt, span_lint_and_then, in_external_macro}; +use utils::{constants, in_external_macro, snippet, snippet_opt, span_help_and_lint, span_lint, span_lint_and_then}; /// **What it does:** Checks for structure field patterns bound to wildcards. /// @@ -251,7 +251,7 @@ impl EarlyLintPass for MiscEarly { UNNEEDED_FIELD_PATTERN, field.span, "You matched a field with a wildcard pattern. Consider using `..` \ - instead", + instead", &format!("Try with `{} {{ {}, .. }}`", type_name, normal[..].join(", ")), ); } @@ -276,7 +276,7 @@ impl EarlyLintPass for MiscEarly { *correspondence, &format!( "`{}` already exists, having another argument having almost the same \ - name makes code comprehension and documentation more difficult", + name makes code comprehension and documentation more difficult", arg_name[1..].to_owned() ), );; @@ -293,30 +293,28 @@ impl EarlyLintPass for MiscEarly { return; } match expr.node { - ExprKind::Call(ref paren, _) => { - if let ExprKind::Paren(ref closure) = paren.node { - if let ExprKind::Closure(_, ref decl, ref block, _) = closure.node { - span_lint_and_then(cx, - REDUNDANT_CLOSURE_CALL, - expr.span, - "Try not to call a closure in the expression where it is declared.", - |db| if decl.inputs.is_empty() { - let hint = snippet(cx, block.span, "..").into_owned(); - db.span_suggestion(expr.span, "Try doing something like: ", hint); - }); - } - } - }, - ExprKind::Unary(UnOp::Neg, ref inner) => { - if let ExprKind::Unary(UnOp::Neg, _) = inner.node { - span_lint( + ExprKind::Call(ref paren, _) => if let ExprKind::Paren(ref closure) = paren.node { + if let ExprKind::Closure(_, ref decl, ref block, _) = closure.node { + span_lint_and_then( cx, - DOUBLE_NEG, + REDUNDANT_CLOSURE_CALL, expr.span, - "`--x` could be misinterpreted as pre-decrement by C programmers, is usually a no-op", + "Try not to call a closure in the expression where it is declared.", + |db| if decl.inputs.is_empty() { + let hint = snippet(cx, block.span, "..").into_owned(); + db.span_suggestion(expr.span, "Try doing something like: ", hint); + }, ); } }, + ExprKind::Unary(UnOp::Neg, ref inner) => if let ExprKind::Unary(UnOp::Neg, _) = inner.node { + span_lint( + cx, + DOUBLE_NEG, + expr.span, + "`--x` could be misinterpreted as pre-decrement by C programmers, is usually a no-op", + ); + }, ExprKind::Lit(ref lit) => self.check_lit(cx, lit), _ => (), } diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index 9ce7df474a3d..81a8b4ffb2e4 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -18,7 +18,7 @@ // [`missing_doc`]: // https://github. // com/rust-lang/rust/blob/d6d05904697d89099b55da3331155392f1db9c00/src/librustc_lint/builtin. -// +// // // // @@ -64,13 +64,15 @@ impl ::std::default::Default for MissingDoc { impl MissingDoc { pub fn new() -> Self { - Self { doc_hidden_stack: vec![false] } + Self { + doc_hidden_stack: vec![false], + } } fn doc_hidden(&self) -> bool { - *self.doc_hidden_stack.last().expect( - "empty doc_hidden_stack", - ) + *self.doc_hidden_stack + .last() + .expect("empty doc_hidden_stack") } fn check_missing_docs_attrs(&self, cx: &LateContext, attrs: &[ast::Attribute], sp: Span, desc: &'static str) { @@ -89,9 +91,9 @@ impl MissingDoc { return; } - let has_doc = attrs.iter().any(|a| { - a.is_value_str() && a.name().map_or(false, |n| n == "doc") - }); + let has_doc = attrs + .iter() + .any(|a| a.is_value_str() && a.name().map_or(false, |n| n == "doc")); if !has_doc { cx.span_lint( MISSING_DOCS_IN_PRIVATE_ITEMS, @@ -110,14 +112,12 @@ impl LintPass for MissingDoc { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { fn enter_lint_attrs(&mut self, _: &LateContext<'a, 'tcx>, attrs: &'tcx [ast::Attribute]) { - let doc_hidden = self.doc_hidden() || - attrs.iter().any(|attr| { - attr.check_name("doc") && - match attr.meta_item_list() { - None => false, - Some(l) => attr::list_contains_name(&l[..], "hidden"), - } - }); + let doc_hidden = self.doc_hidden() || attrs.iter().any(|attr| { + attr.check_name("doc") && match attr.meta_item_list() { + None => false, + Some(l) => attr::list_contains_name(&l[..], "hidden"), + } + }); self.doc_hidden_stack.push(doc_hidden); } @@ -166,10 +166,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { let def_id = cx.tcx.hir.local_def_id(impl_item.id); match cx.tcx.associated_item(def_id).container { ty::TraitContainer(_) => return, - ty::ImplContainer(cid) => { - if cx.tcx.impl_trait_ref(cid).is_some() { - return; - } + ty::ImplContainer(cid) => if cx.tcx.impl_trait_ref(cid).is_some() { + return; }, } diff --git a/clippy_lints/src/mut_mut.rs b/clippy_lints/src/mut_mut.rs index e81330504758..c12d3dde2be2 100644 --- a/clippy_lints/src/mut_mut.rs +++ b/clippy_lints/src/mut_mut.rs @@ -70,7 +70,14 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for MutVisitor<'a, 'tcx> { expr.span, "generally you want to avoid `&mut &mut _` if possible", ); - } else if let ty::TyRef(_, ty::TypeAndMut { mutbl: hir::MutMutable, .. }) = self.cx.tables.expr_ty(e).sty { + } else if let ty::TyRef( + _, + ty::TypeAndMut { + mutbl: hir::MutMutable, + .. + }, + ) = self.cx.tables.expr_ty(e).sty + { span_lint( self.cx, MUT_MUT, @@ -82,13 +89,22 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for MutVisitor<'a, 'tcx> { } fn visit_ty(&mut self, ty: &'tcx hir::Ty) { - if let hir::TyRptr(_, - hir::MutTy { - ty: ref pty, - mutbl: hir::MutMutable, - }) = ty.node + if let hir::TyRptr( + _, + hir::MutTy { + ty: ref pty, + mutbl: hir::MutMutable, + }, + ) = ty.node { - if let hir::TyRptr(_, hir::MutTy { mutbl: hir::MutMutable, .. }) = pty.node { + if let hir::TyRptr( + _, + hir::MutTy { + mutbl: hir::MutMutable, + .. + }, + ) = pty.node + { span_lint( self.cx, MUT_MUT, @@ -96,7 +112,6 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for MutVisitor<'a, 'tcx> { "generally you want to avoid `&mut &mut _` if possible", ); } - } intravisit::walk_ty(self, ty); diff --git a/clippy_lints/src/mut_reference.rs b/clippy_lints/src/mut_reference.rs index 6a7b45bfbfb3..63ccc77a03dc 100644 --- a/clippy_lints/src/mut_reference.rs +++ b/clippy_lints/src/mut_reference.rs @@ -36,15 +36,13 @@ impl LintPass for UnnecessaryMutPassed { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnecessaryMutPassed { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { match e.node { - ExprCall(ref fn_expr, ref arguments) => { - if let ExprPath(ref path) = fn_expr.node { - check_arguments( - cx, - arguments, - cx.tables.expr_ty(fn_expr), - &print::to_string(print::NO_ANN, |s| s.print_qpath(path, false)), - ); - } + ExprCall(ref fn_expr, ref arguments) => if let ExprPath(ref path) = fn_expr.node { + check_arguments( + cx, + arguments, + cx.tables.expr_ty(fn_expr), + &print::to_string(print::NO_ANN, |s| s.print_qpath(path, false)), + ); }, ExprMethodCall(ref path, _, ref arguments) => { let def_id = cx.tables.type_dependent_defs()[e.hir_id].def_id(); @@ -63,16 +61,23 @@ fn check_arguments<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arguments: &[Expr], typ let parameters = type_definition.fn_sig(cx.tcx).skip_binder().inputs(); for (argument, parameter) in arguments.iter().zip(parameters.iter()) { match parameter.sty { - ty::TyRef(_, ty::TypeAndMut { mutbl: MutImmutable, .. }) | - ty::TyRawPtr(ty::TypeAndMut { mutbl: MutImmutable, .. }) => { - if let ExprAddrOf(MutMutable, _) = argument.node { - span_lint( - cx, - UNNECESSARY_MUT_PASSED, - argument.span, - &format!("The function/method `{}` doesn't need a mutable reference", name), - ); - } + ty::TyRef( + _, + ty::TypeAndMut { + mutbl: MutImmutable, + .. + }, + ) | + ty::TyRawPtr(ty::TypeAndMut { + mutbl: MutImmutable, + .. + }) => if let ExprAddrOf(MutMutable, _) = argument.node { + span_lint( + cx, + UNNECESSARY_MUT_PASSED, + argument.span, + &format!("The function/method `{}` doesn't need a mutable reference", name), + ); }, _ => (), } diff --git a/clippy_lints/src/mutex_atomic.rs b/clippy_lints/src/mutex_atomic.rs index 25a7118ceda5..6fe365fd2554 100644 --- a/clippy_lints/src/mutex_atomic.rs +++ b/clippy_lints/src/mutex_atomic.rs @@ -2,7 +2,7 @@ //! //! This lint is **warn** by default -use rustc::lint::{LintPass, LintArray, LateLintPass, LateContext}; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::ty::{self, Ty}; use rustc::hir::Expr; use syntax::ast; @@ -65,7 +65,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutexAtomic { if let Some(atomic_name) = get_atomic_name(mutex_param) { let msg = format!( "Consider using an {} instead of a Mutex here. If you just want the locking \ - behaviour and not the internal type, consider using Mutex<()>.", + behaviour and not the internal type, consider using Mutex<()>.", atomic_name ); match mutex_param.sty { diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index 52f0df12bcdc..bc93190cd09c 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -6,7 +6,7 @@ use rustc::lint::*; use rustc::hir::*; use syntax::ast::LitKind; use syntax::codemap::Spanned; -use utils::{span_lint, span_lint_and_sugg, snippet}; +use utils::{snippet, span_lint, span_lint_and_sugg}; use utils::sugg::Sugg; /// **What it does:** Checks for expressions of the form `if c { true } else { @@ -82,8 +82,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBool { }; if let ExprBlock(ref then_block) = then_block.node { match (fetch_bool_block(then_block), fetch_bool_expr(else_expr)) { - (RetBool(true), RetBool(true)) | - (Bool(true), Bool(true)) => { + (RetBool(true), RetBool(true)) | (Bool(true), Bool(true)) => { span_lint( cx, NEEDLESS_BOOL, @@ -91,8 +90,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBool { "this if-then-else expression will always return true", ); }, - (RetBool(false), RetBool(false)) | - (Bool(false), Bool(false)) => { + (RetBool(false), RetBool(false)) | (Bool(false), Bool(false)) => { span_lint( cx, NEEDLESS_BOOL, @@ -186,16 +184,14 @@ enum Expression { fn fetch_bool_block(block: &Block) -> Expression { match (&*block.stmts, block.expr.as_ref()) { (&[], Some(e)) => fetch_bool_expr(&**e), - (&[ref e], None) => { - if let StmtSemi(ref e, _) = e.node { - if let ExprRet(_) = e.node { - fetch_bool_expr(&**e) - } else { - Expression::Other - } + (&[ref e], None) => if let StmtSemi(ref e, _) = e.node { + if let ExprRet(_) = e.node { + fetch_bool_expr(&**e) } else { Expression::Other } + } else { + Expression::Other }, _ => Expression::Other, } @@ -204,18 +200,14 @@ fn fetch_bool_block(block: &Block) -> Expression { fn fetch_bool_expr(expr: &Expr) -> Expression { match expr.node { ExprBlock(ref block) => fetch_bool_block(block), - ExprLit(ref lit_ptr) => { - if let LitKind::Bool(value) = lit_ptr.node { - Expression::Bool(value) - } else { - Expression::Other - } + ExprLit(ref lit_ptr) => if let LitKind::Bool(value) = lit_ptr.node { + Expression::Bool(value) + } else { + Expression::Other }, - ExprRet(Some(ref expr)) => { - match fetch_bool_expr(expr) { - Expression::Bool(value) => Expression::RetBool(value), - _ => Expression::Other, - } + ExprRet(Some(ref expr)) => match fetch_bool_expr(expr) { + Expression::Bool(value) => Expression::RetBool(value), + _ => Expression::Other, }, _ => Expression::Other, } diff --git a/clippy_lints/src/needless_borrow.rs b/clippy_lints/src/needless_borrow.rs index b331d6910a3b..7dd42bca3ab7 100644 --- a/clippy_lints/src/needless_borrow.rs +++ b/clippy_lints/src/needless_borrow.rs @@ -3,10 +3,10 @@ //! This lint is **warn** by default use rustc::lint::*; -use rustc::hir::{ExprAddrOf, Expr, MutImmutable, Pat, PatKind, BindingAnnotation}; +use rustc::hir::{BindingAnnotation, Expr, ExprAddrOf, MutImmutable, Pat, PatKind}; use rustc::ty; -use rustc::ty::adjustment::{Adjustment, Adjust}; -use utils::{span_lint, in_macro}; +use rustc::ty::adjustment::{Adjust, Adjustment}; +use utils::{in_macro, span_lint}; /// **What it does:** Checks for address of operations (`&`) that are going to /// be dereferenced immediately by the compiler. @@ -43,16 +43,24 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrow { if let ExprAddrOf(MutImmutable, ref inner) = e.node { if let ty::TyRef(..) = cx.tables.expr_ty(inner).sty { for adj3 in cx.tables.expr_adjustments(e).windows(3) { - if let [ - Adjustment { kind: Adjust::Deref(_), .. }, - Adjustment { kind: Adjust::Deref(_), .. }, - Adjustment { kind: Adjust::Borrow(_), .. } - ] = *adj3 { - span_lint(cx, - NEEDLESS_BORROW, - e.span, - "this expression borrows a reference that is immediately dereferenced by the \ - compiler"); + if let [Adjustment { + kind: Adjust::Deref(_), + .. + }, Adjustment { + kind: Adjust::Deref(_), + .. + }, Adjustment { + kind: Adjust::Borrow(_), + .. + }] = *adj3 + { + span_lint( + cx, + NEEDLESS_BORROW, + e.span, + "this expression borrows a reference that is immediately dereferenced by the \ + compiler", + ); } } } diff --git a/clippy_lints/src/needless_borrowed_ref.rs b/clippy_lints/src/needless_borrowed_ref.rs index 0aa741db0762..1c00263cbc2d 100644 --- a/clippy_lints/src/needless_borrowed_ref.rs +++ b/clippy_lints/src/needless_borrowed_ref.rs @@ -3,8 +3,8 @@ //! This lint is **warn** by default use rustc::lint::*; -use rustc::hir::{MutImmutable, Pat, PatKind, BindingAnnotation}; -use utils::{span_lint_and_then, in_macro, snippet}; +use rustc::hir::{BindingAnnotation, MutImmutable, Pat, PatKind}; +use utils::{in_macro, snippet, span_lint_and_then}; /// **What it does:** Checks for useless borrowed references. /// diff --git a/clippy_lints/src/needless_continue.rs b/clippy_lints/src/needless_continue.rs index 692fa19f3ba1..b369d8b570be 100644 --- a/clippy_lints/src/needless_continue.rs +++ b/clippy_lints/src/needless_continue.rs @@ -32,7 +32,7 @@ use syntax::ast; use syntax::codemap::{original_sp, DUMMY_SP}; use std::borrow::Cow; -use utils::{in_macro, span_help_and_lint, snippet_block, snippet, trim_multiline}; +use utils::{in_macro, snippet, snippet_block, span_help_and_lint, trim_multiline}; /// **What it does:** The lint checks for `if`-statements appearing in loops /// that contain a `continue` statement in either their main blocks or their @@ -181,13 +181,10 @@ fn needless_continue_in_else(else_expr: &ast::Expr) -> bool { fn is_first_block_stmt_continue(block: &ast::Block) -> bool { block.stmts.get(0).map_or(false, |stmt| match stmt.node { - ast::StmtKind::Semi(ref e) | - ast::StmtKind::Expr(ref e) => { - if let ast::ExprKind::Continue(_) = e.node { - true - } else { - false - } + ast::StmtKind::Semi(ref e) | ast::StmtKind::Expr(ref e) => if let ast::ExprKind::Continue(_) = e.node { + true + } else { + false }, _ => false, }) @@ -222,8 +219,7 @@ where F: FnMut(&ast::Expr, &ast::Expr, &ast::Block, &ast::Expr), { match stmt.node { - ast::StmtKind::Semi(ref e) | - ast::StmtKind::Expr(ref e) => { + ast::StmtKind::Semi(ref e) | ast::StmtKind::Expr(ref e) => { if let ast::ExprKind::If(ref cond, ref if_block, Some(ref else_expr)) = e.node { func(e, cond, if_block, else_expr); } @@ -269,25 +265,20 @@ const DROP_ELSE_BLOCK_MSG: &'static str = "Consider dropping the else clause, an fn emit_warning<'a>(ctx: &EarlyContext, data: &'a LintData, header: &str, typ: LintType) { - // snip is the whole *help* message that appears after the warning. // message is the warning message. // expr is the expression which the lint warning message refers to. let (snip, message, expr) = match typ { - LintType::ContinueInsideElseBlock => { - ( - suggestion_snippet_for_continue_inside_else(ctx, data, header), - MSG_REDUNDANT_ELSE_BLOCK, - data.else_expr, - ) - }, - LintType::ContinueInsideThenBlock => { - ( - suggestion_snippet_for_continue_inside_if(ctx, data, header), - MSG_ELSE_BLOCK_NOT_NEEDED, - data.if_expr, - ) - }, + LintType::ContinueInsideElseBlock => ( + suggestion_snippet_for_continue_inside_else(ctx, data, header), + MSG_REDUNDANT_ELSE_BLOCK, + data.else_expr, + ), + LintType::ContinueInsideThenBlock => ( + suggestion_snippet_for_continue_inside_if(ctx, data, header), + MSG_ELSE_BLOCK_NOT_NEEDED, + data.if_expr, + ), }; span_help_and_lint(ctx, NEEDLESS_CONTINUE, expr.span, message, &snip); } diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 89ef4ff67f32..f53e85210763 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -9,9 +9,9 @@ use rustc::middle::mem_categorization as mc; use syntax::ast::NodeId; use syntax_pos::Span; use syntax::errors::DiagnosticBuilder; -use utils::{in_macro, is_self, is_copy, implements_trait, get_trait_def_id, match_type, snippet, span_lint_and_then, - multispan_sugg, paths}; -use std::collections::{HashSet, HashMap}; +use utils::{get_trait_def_id, implements_trait, in_macro, is_copy, is_self, match_type, multispan_sugg, paths, + snippet, span_lint_and_then}; +use std::collections::{HashMap, HashSet}; /// **What it does:** Checks for functions taking arguments by value, but not /// consuming them in its @@ -62,16 +62,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { } match kind { - FnKind::ItemFn(.., attrs) => { - for a in attrs { - if_let_chain!{[ - a.meta_item_list().is_some(), - let Some(name) = a.name(), - name == "proc_macro_derive", - ], { - return; - }} - } + FnKind::ItemFn(.., attrs) => for a in attrs { + if_let_chain!{[ + a.meta_item_list().is_some(), + let Some(name) = a.name(), + name == "proc_macro_derive", + ], { + return; + }} }, _ => return, } @@ -106,7 +104,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { let fn_sig = cx.tcx.erase_late_bound_regions(&fn_sig); for ((input, &ty), arg) in decl.inputs.iter().zip(fn_sig.inputs()).zip(&body.arguments) { - // Determines whether `ty` implements `Borrow` (U != ty) specifically. // This is needed due to the `Borrow for T` blanket impl. let implements_borrow_trait = preds @@ -118,9 +115,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { }) .filter(|tpred| tpred.def_id() == borrow_trait && tpred.self_ty() == ty) .any(|tpred| { - tpred.input_types().nth(1).expect( - "Borrow trait must have an parameter", - ) != ty + tpred + .input_types() + .nth(1) + .expect("Borrow trait must have an parameter") != ty }); if_let_chain! {[ @@ -299,8 +297,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for MovedVariablesCtxt<'a, 'tcx> { fn unwrap_downcast_or_interior(mut cmt: mc::cmt) -> mc::cmt { loop { match cmt.cat.clone() { - mc::Categorization::Downcast(c, _) | - mc::Categorization::Interior(c, _) => { + mc::Categorization::Downcast(c, _) | mc::Categorization::Interior(c, _) => { cmt = c; }, _ => return cmt, diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index c6bd91919f5b..1c5524af68e7 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -115,43 +115,42 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { return; } if decl.inputs.is_empty() && name == "new" && cx.access_levels.is_reachable(id) { - let self_ty = cx.tcx.type_of( - cx.tcx.hir.local_def_id(cx.tcx.hir.get_parent(id)), - ); + let self_ty = cx.tcx + .type_of(cx.tcx.hir.local_def_id(cx.tcx.hir.get_parent(id))); if_let_chain!{[ - same_tys(cx, self_ty, return_ty(cx, id)), - let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT), - !implements_trait(cx, self_ty, default_trait_id, &[]) - ], { - if let Some(sp) = can_derive_default(self_ty, cx, default_trait_id) { - span_lint_and_then(cx, - NEW_WITHOUT_DEFAULT_DERIVE, span, - &format!("you should consider deriving a \ - `Default` implementation for `{}`", - self_ty), - |db| { - db.suggest_item_with_attr(cx, sp, "try this", "#[derive(Default)]"); - }); - } else { - span_lint_and_then(cx, - NEW_WITHOUT_DEFAULT, span, - &format!("you should consider adding a \ - `Default` implementation for `{}`", - self_ty), - |db| { - db.suggest_prepend_item(cx, - span, - "try this", - &format!( + same_tys(cx, self_ty, return_ty(cx, id)), + let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT), + !implements_trait(cx, self_ty, default_trait_id, &[]) + ], { + if let Some(sp) = can_derive_default(self_ty, cx, default_trait_id) { + span_lint_and_then(cx, + NEW_WITHOUT_DEFAULT_DERIVE, span, + &format!("you should consider deriving a \ + `Default` implementation for `{}`", + self_ty), + |db| { + db.suggest_item_with_attr(cx, sp, "try this", "#[derive(Default)]"); + }); + } else { + span_lint_and_then(cx, + NEW_WITHOUT_DEFAULT, span, + &format!("you should consider adding a \ + `Default` implementation for `{}`", + self_ty), + |db| { + db.suggest_prepend_item(cx, + span, + "try this", + &format!( "impl Default for {} {{ fn default() -> Self {{ Self::new() }} }}", - self_ty)); - }); - } - }} + self_ty)); + }); + } + }} } } } diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index 971309adb330..1d5e51187bbd 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -1,7 +1,7 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::hir::def::Def; -use rustc::hir::{Expr, Expr_, Stmt, StmtSemi, BlockCheckMode, UnsafeSource, BiAnd, BiOr}; -use utils::{in_macro, span_lint, snippet_opt, span_lint_and_sugg}; +use rustc::hir::{BiAnd, BiOr, BlockCheckMode, Expr, Expr_, Stmt, StmtSemi, UnsafeSource}; +use utils::{in_macro, snippet_opt, span_lint, span_lint_and_sugg}; use std::ops::Deref; /// **What it does:** Checks for statements which have no effect. @@ -45,13 +45,11 @@ fn has_no_effect(cx: &LateContext, expr: &Expr) -> bool { return false; } match expr.node { - Expr_::ExprLit(..) | - Expr_::ExprClosure(.., _) | - Expr_::ExprPath(..) => true, - Expr_::ExprIndex(ref a, ref b) | - Expr_::ExprBinary(_, ref a, ref b) => has_no_effect(cx, a) && has_no_effect(cx, b), - Expr_::ExprArray(ref v) | - Expr_::ExprTup(ref v) => v.iter().all(|val| has_no_effect(cx, val)), + Expr_::ExprLit(..) | Expr_::ExprClosure(.., _) | Expr_::ExprPath(..) => true, + Expr_::ExprIndex(ref a, ref b) | Expr_::ExprBinary(_, ref a, ref b) => { + has_no_effect(cx, a) && has_no_effect(cx, b) + }, + Expr_::ExprArray(ref v) | Expr_::ExprTup(ref v) => v.iter().all(|val| has_no_effect(cx, val)), Expr_::ExprRepeat(ref inner, _) | Expr_::ExprCast(ref inner, _) | Expr_::ExprType(ref inner, _) | @@ -61,34 +59,29 @@ fn has_no_effect(cx: &LateContext, expr: &Expr) -> bool { Expr_::ExprAddrOf(_, ref inner) | Expr_::ExprBox(ref inner) => has_no_effect(cx, inner), Expr_::ExprStruct(_, ref fields, ref base) => { - fields.iter().all(|field| has_no_effect(cx, &field.expr)) && - match *base { - Some(ref base) => has_no_effect(cx, base), - None => true, - } + fields.iter().all(|field| has_no_effect(cx, &field.expr)) && match *base { + Some(ref base) => has_no_effect(cx, base), + None => true, + } }, - Expr_::ExprCall(ref callee, ref args) => { - if let Expr_::ExprPath(ref qpath) = callee.node { - let def = cx.tables.qpath_def(qpath, callee.hir_id); - match def { - Def::Struct(..) | - Def::Variant(..) | - Def::StructCtor(..) | - Def::VariantCtor(..) => args.iter().all(|arg| has_no_effect(cx, arg)), - _ => false, - } + Expr_::ExprCall(ref callee, ref args) => if let Expr_::ExprPath(ref qpath) = callee.node { + let def = cx.tables.qpath_def(qpath, callee.hir_id); + match def { + Def::Struct(..) | Def::Variant(..) | Def::StructCtor(..) | Def::VariantCtor(..) => { + args.iter().all(|arg| has_no_effect(cx, arg)) + }, + _ => false, + } + } else { + false + }, + Expr_::ExprBlock(ref block) => { + block.stmts.is_empty() && if let Some(ref expr) = block.expr { + has_no_effect(cx, expr) } else { false } }, - Expr_::ExprBlock(ref block) => { - block.stmts.is_empty() && - if let Some(ref expr) = block.expr { - has_no_effect(cx, expr) - } else { - false - } - }, _ => false, } } @@ -143,8 +136,7 @@ fn reduce_expression<'a>(cx: &LateContext, expr: &'a Expr) -> Option { Some(vec![&**a, &**b]) }, - Expr_::ExprArray(ref v) | - Expr_::ExprTup(ref v) => Some(v.iter().collect()), + Expr_::ExprArray(ref v) | Expr_::ExprTup(ref v) => Some(v.iter().collect()), Expr_::ExprRepeat(ref inner, _) | Expr_::ExprCast(ref inner, _) | Expr_::ExprType(ref inner, _) | @@ -153,29 +145,24 @@ fn reduce_expression<'a>(cx: &LateContext, expr: &'a Expr) -> Option reduce_expression(cx, inner).or_else(|| Some(vec![inner])), - Expr_::ExprStruct(_, ref fields, ref base) => { - Some( - fields - .iter() - .map(|f| &f.expr) - .chain(base) - .map(Deref::deref) - .collect(), - ) - }, - Expr_::ExprCall(ref callee, ref args) => { - if let Expr_::ExprPath(ref qpath) = callee.node { - let def = cx.tables.qpath_def(qpath, callee.hir_id); - match def { - Def::Struct(..) | - Def::Variant(..) | - Def::StructCtor(..) | - Def::VariantCtor(..) => Some(args.iter().collect()), - _ => None, - } - } else { - None + Expr_::ExprStruct(_, ref fields, ref base) => Some( + fields + .iter() + .map(|f| &f.expr) + .chain(base) + .map(Deref::deref) + .collect(), + ), + Expr_::ExprCall(ref callee, ref args) => if let Expr_::ExprPath(ref qpath) = callee.node { + let def = cx.tables.qpath_def(qpath, callee.hir_id); + match def { + Def::Struct(..) | Def::Variant(..) | Def::StructCtor(..) | Def::VariantCtor(..) => { + Some(args.iter().collect()) + }, + _ => None, } + } else { + None }, Expr_::ExprBlock(ref block) => { if block.stmts.is_empty() { diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index c584e3b1a9e2..d36054eacf4b 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -3,8 +3,8 @@ use syntax::codemap::Span; use syntax::symbol::InternedString; use syntax::ast::*; use syntax::attr; -use syntax::visit::{Visitor, walk_block, walk_pat, walk_expr}; -use utils::{span_lint_and_then, in_macro, span_lint}; +use syntax::visit::{walk_block, walk_expr, walk_pat, Visitor}; +use utils::{in_macro, span_lint, span_lint_and_then}; /// **What it does:** Checks for names that are very similar and thus confusing. /// @@ -82,11 +82,9 @@ impl<'a, 'tcx: 'a, 'b> Visitor<'tcx> for SimilarNamesNameVisitor<'a, 'tcx, 'b> { fn visit_pat(&mut self, pat: &'tcx Pat) { match pat.node { PatKind::Ident(_, id, _) => self.check_name(id.span, id.node.name), - PatKind::Struct(_, ref fields, _) => { - for field in fields { - if !field.node.is_shorthand { - self.visit_pat(&field.node.pat); - } + PatKind::Struct(_, ref fields, _) => for field in fields { + if !field.node.is_shorthand { + self.visit_pat(&field.node.pat); } }, _ => walk_pat(self, pat), @@ -104,9 +102,8 @@ fn get_whitelist(interned_name: &str) -> Option<&'static [&'static str]> { } fn whitelisted(interned_name: &str, list: &[&str]) -> bool { - list.iter().any(|&name| { - interned_name.starts_with(name) || interned_name.ends_with(name) - }) + list.iter() + .any(|&name| interned_name.starts_with(name) || interned_name.ends_with(name)) } impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> { @@ -157,21 +154,21 @@ impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> { } else { let mut interned_chars = interned_name.chars(); let mut existing_chars = existing_name.interned.chars(); - let first_i = interned_chars.next().expect( - "we know we have at least one char", - ); - let first_e = existing_chars.next().expect( - "we know we have at least one char", - ); + let first_i = interned_chars + .next() + .expect("we know we have at least one char"); + let first_e = existing_chars + .next() + .expect("we know we have at least one char"); let eq_or_numeric = |(a, b): (char, char)| a == b || a.is_numeric() && b.is_numeric(); if eq_or_numeric((first_i, first_e)) { - let last_i = interned_chars.next_back().expect( - "we know we have at least two chars", - ); - let last_e = existing_chars.next_back().expect( - "we know we have at least two chars", - ); + let last_i = interned_chars + .next_back() + .expect("we know we have at least two chars"); + let last_e = existing_chars + .next_back() + .expect("we know we have at least two chars"); if eq_or_numeric((last_i, last_e)) { if interned_chars .zip(existing_chars) @@ -181,12 +178,12 @@ impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> { continue; } } else { - let second_last_i = interned_chars.next_back().expect( - "we know we have at least three chars", - ); - let second_last_e = existing_chars.next_back().expect( - "we know we have at least three chars", - ); + let second_last_i = interned_chars + .next_back() + .expect("we know we have at least three chars"); + let second_last_e = existing_chars + .next_back() + .expect("we know we have at least three chars"); if !eq_or_numeric((second_last_i, second_last_e)) || second_last_i == '_' || !interned_chars.zip(existing_chars).all(eq_or_numeric) { @@ -197,12 +194,12 @@ impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> { split_at = interned_name.char_indices().rev().next().map(|(i, _)| i); } } else { - let second_i = interned_chars.next().expect( - "we know we have at least two chars", - ); - let second_e = existing_chars.next().expect( - "we know we have at least two chars", - ); + let second_i = interned_chars + .next() + .expect("we know we have at least two chars"); + let second_e = existing_chars + .next() + .expect("we know we have at least two chars"); if !eq_or_numeric((second_i, second_e)) || second_i == '_' || !interned_chars.zip(existing_chars).all(eq_or_numeric) { @@ -225,7 +222,7 @@ impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> { span, &format!( "separate the discriminating character by an \ - underscore like: `{}_{}`", + underscore like: `{}_{}`", &interned_name[..split], &interned_name[split..] ), diff --git a/clippy_lints/src/ok_if_let.rs b/clippy_lints/src/ok_if_let.rs index ee55ea882b08..67d39333ff98 100644 --- a/clippy_lints/src/ok_if_let.rs +++ b/clippy_lints/src/ok_if_let.rs @@ -1,6 +1,6 @@ use rustc::lint::*; use rustc::hir::*; -use utils::{paths, method_chain_args, span_help_and_lint, match_type, snippet}; +use utils::{match_type, method_chain_args, paths, snippet, span_help_and_lint}; /// **What it does:*** Checks for unnecessary `ok()` in if let. /// diff --git a/clippy_lints/src/open_options.rs b/clippy_lints/src/open_options.rs index e67c1f4d1488..627608889337 100644 --- a/clippy_lints/src/open_options.rs +++ b/clippy_lints/src/open_options.rs @@ -1,4 +1,4 @@ -use rustc::hir::{Expr, ExprMethodCall, ExprLit}; +use rustc::hir::{Expr, ExprLit, ExprMethodCall}; use rustc::lint::*; use syntax::ast::LitKind; use syntax::codemap::{Span, Spanned}; @@ -67,11 +67,18 @@ fn get_open_options(cx: &LateContext, argument: &Expr, options: &mut Vec<(OpenOp // Only proceed if this is a call on some object of type std::fs::OpenOptions if match_type(cx, obj_ty, &paths::OPEN_OPTIONS) && arguments.len() >= 2 { - let argument_option = match arguments[1].node { ExprLit(ref span) => { - if let Spanned { node: LitKind::Bool(lit), .. } = **span { - if lit { Argument::True } else { Argument::False } + if let Spanned { + node: LitKind::Bool(lit), + .. + } = **span + { + if lit { + Argument::True + } else { + Argument::False + } } else { return; // The function is called with a literal // which is not a boolean literal. This is theoretically diff --git a/clippy_lints/src/panic.rs b/clippy_lints/src/panic.rs index 70ee7de7b4d9..a050873187d0 100644 --- a/clippy_lints/src/panic.rs +++ b/clippy_lints/src/panic.rs @@ -1,7 +1,7 @@ use rustc::hir::*; use rustc::lint::*; use syntax::ast::LitKind; -use utils::{is_direct_expn_of, match_def_path, resolve_node, paths, span_lint}; +use utils::{is_direct_expn_of, match_def_path, paths, resolve_node, span_lint}; /// **What it does:** Checks for missing parameters in `panic!`. /// diff --git a/clippy_lints/src/precedence.rs b/clippy_lints/src/precedence.rs index f5a6833b4b02..e06c571b6f6d 100644 --- a/clippy_lints/src/precedence.rs +++ b/clippy_lints/src/precedence.rs @@ -1,7 +1,7 @@ use rustc::lint::*; use syntax::ast::*; use syntax::codemap::Spanned; -use utils::{span_lint_and_sugg, snippet}; +use utils::{snippet, span_lint_and_sugg}; /// **What it does:** Checks for operations where precedence may be unclear /// and suggests to add parentheses. Currently it catches the following: @@ -89,9 +89,7 @@ impl EarlyLintPass for Precedence { if let Some(slf) = args.first() { if let ExprKind::Lit(ref lit) = slf.node { match lit.node { - LitKind::Int(..) | - LitKind::Float(..) | - LitKind::FloatUnsuffixed(..) => { + LitKind::Int(..) | LitKind::Float(..) | LitKind::FloatUnsuffixed(..) => { span_lint_and_sugg( cx, PRECEDENCE, diff --git a/clippy_lints/src/print.rs b/clippy_lints/src/print.rs index 982b46e20d3d..9aca75433962 100644 --- a/clippy_lints/src/print.rs +++ b/clippy_lints/src/print.rs @@ -1,8 +1,8 @@ use rustc::hir::*; -use rustc::hir::map::Node::{NodeItem, NodeImplItem}; +use rustc::hir::map::Node::{NodeImplItem, NodeItem}; use rustc::lint::*; use utils::paths; -use utils::{is_expn_of, match_def_path, resolve_node, span_lint, match_path}; +use utils::{is_expn_of, match_def_path, match_path, resolve_node, span_lint}; use format::get_argument_fmtstr_parts; /// **What it does:** This lint warns when you using `print!()` with a format diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index a21142a257d7..f12ec039f738 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -128,11 +128,13 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId) { let fn_ty = sig.skip_binder(); for (arg, ty) in decl.inputs.iter().zip(fn_ty.inputs()) { - if let ty::TyRef(_, - ty::TypeAndMut { - ty, - mutbl: MutImmutable, - }) = ty.sty + if let ty::TyRef( + _, + ty::TypeAndMut { + ty, + mutbl: MutImmutable, + }, + ) = ty.sty { if match_type(cx, ty, &paths::VEC) { span_lint( @@ -140,7 +142,7 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId) { PTR_ARG, arg.span, "writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used \ - with non-Vec-based slices. Consider changing the type to `&[...]`", + with non-Vec-based slices. Consider changing the type to `&[...]`", ); } else if match_type(cx, ty, &paths::STRING) { span_lint( @@ -148,7 +150,7 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId) { PTR_ARG, arg.span, "writing `&String` instead of `&str` involves a new object where a slice will do. \ - Consider changing the type to `&str`", + Consider changing the type to `&str`", ); } } @@ -157,10 +159,10 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId) { if let FunctionRetTy::Return(ref ty) = decl.output { if let Some((out, MutMutable, _)) = get_rptr_lm(ty) { let mut immutables = vec![]; - for (_, ref mutbl, ref argspan) in - decl.inputs.iter().filter_map(|ty| get_rptr_lm(ty)).filter( - |&(lt, _, _)| lt.name == out.name, - ) + for (_, ref mutbl, ref argspan) in decl.inputs + .iter() + .filter_map(|ty| get_rptr_lm(ty)) + .filter(|&(lt, _, _)| lt.name == out.name) { if *mutbl == MutMutable { return; diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index aa43fb6b620f..44c909810ea8 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -1,7 +1,7 @@ use rustc::lint::*; use rustc::hir::*; use utils::{is_integer_literal, paths, snippet, span_lint}; -use utils::{higher, implements_trait, get_trait_def_id}; +use utils::{get_trait_def_id, higher, implements_trait}; /// **What it does:** Checks for calling `.step_by(0)` on iterators, /// which never terminates. @@ -54,7 +54,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StepByZero { // Range with step_by(0). if name == "step_by" && args.len() == 2 && has_step_by(cx, &args[0]) { - use consts::{Constant, constant}; + use consts::{constant, Constant}; use rustc_const_math::ConstInt::Usize; if let Some((Constant::Int(Usize(us)), _)) = constant(cx, &args[1]) { if us.as_u64(cx.sess().target.uint_type) == 0 { diff --git a/clippy_lints/src/reference.rs b/clippy_lints/src/reference.rs index a8360c71f912..fce3c6ad2850 100644 --- a/clippy_lints/src/reference.rs +++ b/clippy_lints/src/reference.rs @@ -1,6 +1,6 @@ use syntax::ast::{Expr, ExprKind, UnOp}; use rustc::lint::*; -use utils::{span_lint_and_sugg, snippet}; +use utils::{snippet, span_lint_and_sugg}; /// **What it does:** Checks for usage of `*&` and `*&mut` in expressions. /// diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index c1011168c529..8b5dedfccd44 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -7,9 +7,9 @@ use rustc::ty::subst::Substs; use std::collections::HashSet; use std::error::Error; use syntax::ast::{LitKind, NodeId}; -use syntax::codemap::{Span, BytePos}; +use syntax::codemap::{BytePos, Span}; use syntax::symbol::InternedString; -use utils::{is_expn_of, match_def_path, match_type, paths, span_lint, span_help_and_lint}; +use utils::{is_expn_of, match_def_path, match_type, paths, span_help_and_lint, span_lint}; /// **What it does:** Checks [regex](https://crates.io/crates/regex) creation /// (with `Regex::new`,`RegexBuilder::new` or `RegexSet::new`) for correct @@ -161,27 +161,19 @@ fn is_trivial_regex(s: ®ex_syntax::Expr) -> Option<&'static str> { match *s { Expr::Empty | Expr::StartText | Expr::EndText => Some("the regex is unlikely to be useful as it is"), Expr::Literal { .. } => Some("consider using `str::contains`"), - Expr::Concat(ref exprs) => { - match exprs.len() { - 2 => { - match (&exprs[0], &exprs[1]) { - (&Expr::StartText, &Expr::EndText) => Some("consider using `str::is_empty`"), - (&Expr::StartText, &Expr::Literal { .. }) => Some("consider using `str::starts_with`"), - (&Expr::Literal { .. }, &Expr::EndText) => Some("consider using `str::ends_with`"), - _ => None, - } - }, - 3 => { - if let (&Expr::StartText, &Expr::Literal { .. }, &Expr::EndText) = - (&exprs[0], &exprs[1], &exprs[2]) - { - Some("consider using `==` on `str`s") - } else { - None - } - }, + Expr::Concat(ref exprs) => match exprs.len() { + 2 => match (&exprs[0], &exprs[1]) { + (&Expr::StartText, &Expr::EndText) => Some("consider using `str::is_empty`"), + (&Expr::StartText, &Expr::Literal { .. }) => Some("consider using `str::starts_with`"), + (&Expr::Literal { .. }, &Expr::EndText) => Some("consider using `str::ends_with`"), _ => None, - } + }, + 3 => if let (&Expr::StartText, &Expr::Literal { .. }, &Expr::EndText) = (&exprs[0], &exprs[1], &exprs[2]) { + Some("consider using `==` on `str`s") + } else { + None + }, + _ => None, }, _ => None, } @@ -205,16 +197,14 @@ fn check_regex(cx: &LateContext, expr: &Expr, utf8: bool) { if let LitKind::Str(ref r, _) = lit.node { let r = &r.as_str(); match builder.parse(r) { - Ok(r) => { - if let Some(repl) = is_trivial_regex(&r) { - span_help_and_lint( - cx, - TRIVIAL_REGEX, - expr.span, - "trivial regex", - &format!("consider using {}", repl), - ); - } + Ok(r) => if let Some(repl) = is_trivial_regex(&r) { + span_help_and_lint( + cx, + TRIVIAL_REGEX, + expr.span, + "trivial regex", + &format!("consider using {}", repl), + ); }, Err(e) => { span_lint( @@ -228,16 +218,14 @@ fn check_regex(cx: &LateContext, expr: &Expr, utf8: bool) { } } else if let Some(r) = const_str(cx, expr) { match builder.parse(&r) { - Ok(r) => { - if let Some(repl) = is_trivial_regex(&r) { - span_help_and_lint( - cx, - TRIVIAL_REGEX, - expr.span, - "trivial regex", - &format!("consider using {}", repl), - ); - } + Ok(r) => if let Some(repl) = is_trivial_regex(&r) { + span_help_and_lint( + cx, + TRIVIAL_REGEX, + expr.span, + "trivial regex", + &format!("consider using {}", repl), + ); }, Err(e) => { span_lint( diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index b9fcb62de736..0884ebbf5cf0 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -3,7 +3,7 @@ use syntax::ast; use syntax::codemap::{Span, Spanned}; use syntax::visit::FnKind; -use utils::{span_note_and_lint, span_lint_and_then, snippet_opt, match_path_ast, in_macro, in_external_macro}; +use utils::{in_external_macro, in_macro, match_path_ast, snippet_opt, span_lint_and_then, span_note_and_lint}; /// **What it does:** Checks for return statements at the end of a block. /// @@ -50,8 +50,7 @@ impl ReturnPass { fn check_block_return(&mut self, cx: &EarlyContext, block: &ast::Block) { if let Some(stmt) = block.stmts.last() { match stmt.node { - ast::StmtKind::Expr(ref expr) | - ast::StmtKind::Semi(ref expr) => { + ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => { self.check_final_expr(cx, expr, Some(stmt.span)); }, _ => (), @@ -81,10 +80,8 @@ impl ReturnPass { self.check_final_expr(cx, elsexpr, None); }, // a match expr, check all arms - ast::ExprKind::Match(_, ref arms) => { - for arm in arms { - self.check_final_expr(cx, &arm.body, Some(arm.body.span)); - } + ast::ExprKind::Match(_, ref arms) => for arm in arms { + self.check_final_expr(cx, &arm.body, Some(arm.body.span)); }, _ => (), } @@ -140,8 +137,7 @@ impl LintPass for ReturnPass { impl EarlyLintPass for ReturnPass { fn check_fn(&mut self, cx: &EarlyContext, kind: FnKind, _: &ast::FnDecl, _: Span, _: ast::NodeId) { match kind { - FnKind::ItemFn(.., block) | - FnKind::Method(.., block) => self.check_block_return(cx, block), + FnKind::ItemFn(.., block) | FnKind::Method(.., block) => self.check_block_return(cx, block), FnKind::Closure(body) => self.check_final_expr(cx, body, Some(body.span)), } } diff --git a/clippy_lints/src/serde_api.rs b/clippy_lints/src/serde_api.rs index 4feaaa192878..0ea24a333934 100644 --- a/clippy_lints/src/serde_api.rs +++ b/clippy_lints/src/serde_api.rs @@ -1,6 +1,6 @@ use rustc::lint::*; use rustc::hir::*; -use utils::{span_lint, get_trait_def_id, paths}; +use utils::{get_trait_def_id, paths, span_lint}; /// **What it does:** Checks for mis-uses of the serde API. /// diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index 5649847b3349..f6461b2d4388 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -4,7 +4,7 @@ use rustc::hir::*; use rustc::hir::intravisit::FnKind; use rustc::ty; use syntax::codemap::Span; -use utils::{contains_name, higher, in_external_macro, snippet, span_lint_and_then, iter_input_pats}; +use utils::{contains_name, higher, in_external_macro, iter_input_pats, snippet, span_lint_and_then}; /// **What it does:** Checks for bindings that shadow other bindings already in /// scope, while just changing reference level or mutability. @@ -111,8 +111,7 @@ fn check_block<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, block: &'tcx Block, binding for stmt in &block.stmts { match stmt.node { StmtDecl(ref decl, _) => check_decl(cx, decl, bindings), - StmtExpr(ref e, _) | - StmtSemi(ref e, _) => check_expr(cx, e, bindings), + StmtExpr(ref e, _) | StmtSemi(ref e, _) => check_expr(cx, e, bindings), } } if let Some(ref o) = block.expr { @@ -185,54 +184,49 @@ fn check_pat<'a, 'tcx>( check_pat(cx, p, init, span, bindings); } }, - PatKind::Struct(_, ref pfields, _) => { - if let Some(init_struct) = init { - if let ExprStruct(_, ref efields, _) = init_struct.node { - for field in pfields { - let name = field.node.name; - let efield = efields.iter().find(|f| f.name.node == name).map( - |f| &*f.expr, - ); - check_pat(cx, &field.node.pat, efield, span, bindings); - } - } else { - for field in pfields { - check_pat(cx, &field.node.pat, init, span, bindings); - } + PatKind::Struct(_, ref pfields, _) => if let Some(init_struct) = init { + if let ExprStruct(_, ref efields, _) = init_struct.node { + for field in pfields { + let name = field.node.name; + let efield = efields + .iter() + .find(|f| f.name.node == name) + .map(|f| &*f.expr); + check_pat(cx, &field.node.pat, efield, span, bindings); } } else { for field in pfields { - check_pat(cx, &field.node.pat, None, span, bindings); + check_pat(cx, &field.node.pat, init, span, bindings); } } + } else { + for field in pfields { + check_pat(cx, &field.node.pat, None, span, bindings); + } }, - PatKind::Tuple(ref inner, _) => { - if let Some(init_tup) = init { - if let ExprTup(ref tup) = init_tup.node { - for (i, p) in inner.iter().enumerate() { - check_pat(cx, p, Some(&tup[i]), p.span, bindings); - } - } else { - for p in inner { - check_pat(cx, p, init, span, bindings); - } + PatKind::Tuple(ref inner, _) => if let Some(init_tup) = init { + if let ExprTup(ref tup) = init_tup.node { + for (i, p) in inner.iter().enumerate() { + check_pat(cx, p, Some(&tup[i]), p.span, bindings); } } else { for p in inner { - check_pat(cx, p, None, span, bindings); + check_pat(cx, p, init, span, bindings); } } + } else { + for p in inner { + check_pat(cx, p, None, span, bindings); + } }, - PatKind::Box(ref inner) => { - if let Some(initp) = init { - if let ExprBox(ref inner_init) = initp.node { - check_pat(cx, inner, Some(&**inner_init), span, bindings); - } else { - check_pat(cx, inner, init, span, bindings); - } + PatKind::Box(ref inner) => if let Some(initp) = init { + if let ExprBox(ref inner_init) = initp.node { + check_pat(cx, inner, Some(&**inner_init), span, bindings); } else { check_pat(cx, inner, init, span, bindings); } + } else { + check_pat(cx, inner, init, span, bindings); }, PatKind::Ref(ref inner, _) => check_pat(cx, inner, init, span, bindings), // PatVec(Vec>, Option>, Vec>), @@ -292,13 +286,14 @@ fn lint_shadow<'a, 'tcx: 'a>( }, ); } - } else { - span_lint_and_then(cx, - SHADOW_UNRELATED, - span, - &format!("`{}` shadows a previous declaration", snippet(cx, pattern_span, "_")), - |db| { db.span_note(prev_span, "previous binding is here"); }); + span_lint_and_then( + cx, + SHADOW_UNRELATED, + span, + &format!("`{}` shadows a previous declaration", snippet(cx, pattern_span, "_")), + |db| { db.span_note(prev_span, "previous binding is here"); }, + ); } } @@ -307,19 +302,14 @@ fn check_expr<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, bindings: return; } match expr.node { - ExprUnary(_, ref e) | - ExprField(ref e, _) | - ExprTupField(ref e, _) | - ExprAddrOf(_, ref e) | - ExprBox(ref e) => check_expr(cx, e, bindings), - ExprBlock(ref block) | - ExprLoop(ref block, _, _) => check_block(cx, block, bindings), + ExprUnary(_, ref e) | ExprField(ref e, _) | ExprTupField(ref e, _) | ExprAddrOf(_, ref e) | ExprBox(ref e) => { + check_expr(cx, e, bindings) + }, + ExprBlock(ref block) | ExprLoop(ref block, _, _) => check_block(cx, block, bindings), // ExprCall // ExprMethodCall - ExprArray(ref v) | ExprTup(ref v) => { - for e in v { - check_expr(cx, e, bindings) - } + ExprArray(ref v) | ExprTup(ref v) => for e in v { + check_expr(cx, e, bindings) }, ExprIf(ref cond, ref then, ref otherwise) => { check_expr(cx, cond, bindings); @@ -358,12 +348,9 @@ fn check_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: &'tcx Ty, bindings: &mut V check_ty(cx, fty, bindings); check_expr(cx, &cx.tcx.hir.body(body_id).value, bindings); }, - TyPtr(MutTy { ty: ref mty, .. }) | - TyRptr(_, MutTy { ty: ref mty, .. }) => check_ty(cx, mty, bindings), - TyTup(ref tup) => { - for t in tup { - check_ty(cx, t, bindings) - } + TyPtr(MutTy { ty: ref mty, .. }) | TyRptr(_, MutTy { ty: ref mty, .. }) => check_ty(cx, mty, bindings), + TyTup(ref tup) => for t in tup { + check_ty(cx, t, bindings) }, TyTypeof(body_id) => check_expr(cx, &cx.tcx.hir.body(body_id).value, bindings), _ => (), @@ -372,14 +359,13 @@ fn check_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: &'tcx Ty, bindings: &mut V fn is_self_shadow(name: Name, expr: &Expr) -> bool { match expr.node { - ExprBox(ref inner) | - ExprAddrOf(_, ref inner) => is_self_shadow(name, inner), + ExprBox(ref inner) | ExprAddrOf(_, ref inner) => is_self_shadow(name, inner), ExprBlock(ref block) => { block.stmts.is_empty() && - block.expr.as_ref().map_or( - false, - |e| is_self_shadow(name, e), - ) + block + .expr + .as_ref() + .map_or(false, |e| is_self_shadow(name, e)) }, ExprUnary(op, ref inner) => (UnDeref == op) && is_self_shadow(name, inner), ExprPath(QPath::Resolved(_, ref path)) => path_eq_name(name, path), diff --git a/clippy_lints/src/should_assert_eq.rs b/clippy_lints/src/should_assert_eq.rs index ecb2c9c31624..b8cc6873adc4 100644 --- a/clippy_lints/src/should_assert_eq.rs +++ b/clippy_lints/src/should_assert_eq.rs @@ -1,6 +1,6 @@ use rustc::lint::*; use rustc::hir::*; -use utils::{is_direct_expn_of, is_expn_of, implements_trait, span_lint}; +use utils::{implements_trait, is_direct_expn_of, is_expn_of, span_lint}; /// **What it does:** Checks for `assert!(x == y)` or `assert!(x != y)` which /// can be better written diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index 587ad38c9e50..0365322ef680 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -2,7 +2,7 @@ use rustc::hir::*; use rustc::lint::*; use syntax::codemap::Spanned; use utils::SpanlessEq; -use utils::{match_type, paths, span_lint, span_lint_and_sugg, walk_ptrs_ty, get_parent_expr, is_allowed}; +use utils::{get_parent_expr, is_allowed, match_type, paths, span_lint, span_lint_and_sugg, walk_ptrs_ty}; /// **What it does:** Checks for string appends of the form `x = x + y` (without /// `let`!). @@ -108,7 +108,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringAdd { STRING_ADD_ASSIGN, e.span, "you assigned the result of adding something to this string. Consider using \ - `String::push_str()` instead", + `String::push_str()` instead", ); } } @@ -124,10 +124,10 @@ fn is_add(cx: &LateContext, src: &Expr, target: &Expr) -> bool { ExprBinary(Spanned { node: BiAdd, .. }, ref left, _) => SpanlessEq::new(cx).eq_expr(target, left), ExprBlock(ref block) => { block.stmts.is_empty() && - block.expr.as_ref().map_or( - false, - |expr| is_add(cx, expr, target), - ) + block + .expr + .as_ref() + .map_or(false, |expr| is_add(cx, expr, target)) }, _ => false, } @@ -146,7 +146,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringLitAsBytes { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { use std::ascii::AsciiExt; use syntax::ast::LitKind; - use utils::{snippet, in_macro}; + use utils::{in_macro, snippet}; if let ExprMethodCall(ref path, _, ref args) = e.node { if path.name == "as_bytes" { diff --git a/clippy_lints/src/temporary_assignment.rs b/clippy_lints/src/temporary_assignment.rs index 1669b2d65572..877321255c16 100644 --- a/clippy_lints/src/temporary_assignment.rs +++ b/clippy_lints/src/temporary_assignment.rs @@ -41,11 +41,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if let ExprAssign(ref target, _) = expr.node { match target.node { - ExprField(ref base, _) | - ExprTupField(ref base, _) => { - if is_temporary(base) && !is_adjusted(cx, base) { - span_lint(cx, TEMPORARY_ASSIGNMENT, expr.span, "assignment to temporary"); - } + ExprField(ref base, _) | ExprTupField(ref base, _) => if is_temporary(base) && !is_adjusted(cx, base) { + span_lint(cx, TEMPORARY_ASSIGNMENT, expr.span, "assignment to temporary"); }, _ => (), } diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 83e212c36d15..a590bf744bfa 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -1,7 +1,7 @@ use rustc::lint::*; use rustc::ty::{self, Ty}; use rustc::hir::*; -use utils::{match_def_path, paths, span_lint, span_lint_and_then, snippet, last_path_segment}; +use utils::{last_path_segment, match_def_path, paths, snippet, span_lint, span_lint_and_then}; use utils::sugg; /// **What it does:** Checks for transmutes that can't ever be correct on any @@ -95,103 +95,88 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { let to_ty = cx.tables.expr_ty(e); match (&from_ty.sty, &to_ty.sty) { - _ if from_ty == to_ty => { - span_lint( - cx, - USELESS_TRANSMUTE, - e.span, - &format!("transmute from a type (`{}`) to itself", from_ty), - ) - }, - (&ty::TyRef(_, rty), &ty::TyRawPtr(ptr_ty)) => { - span_lint_and_then( - cx, - USELESS_TRANSMUTE, - e.span, - "transmute from a reference to a pointer", - |db| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { - let sugg = if ptr_ty == rty { - arg.as_ty(to_ty) - } else { - arg.as_ty(cx.tcx.mk_ptr(rty)).as_ty(to_ty) - }; + _ if from_ty == to_ty => span_lint( + cx, + USELESS_TRANSMUTE, + e.span, + &format!("transmute from a type (`{}`) to itself", from_ty), + ), + (&ty::TyRef(_, rty), &ty::TyRawPtr(ptr_ty)) => span_lint_and_then( + cx, + USELESS_TRANSMUTE, + e.span, + "transmute from a reference to a pointer", + |db| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { + let sugg = if ptr_ty == rty { + arg.as_ty(to_ty) + } else { + arg.as_ty(cx.tcx.mk_ptr(rty)).as_ty(to_ty) + }; - db.span_suggestion(e.span, "try", sugg.to_string()); - }, - ) - }, - (&ty::TyInt(_), &ty::TyRawPtr(_)) | - (&ty::TyUint(_), &ty::TyRawPtr(_)) => { - span_lint_and_then( - cx, - USELESS_TRANSMUTE, - e.span, - "transmute from an integer to a pointer", - |db| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { - db.span_suggestion(e.span, "try", arg.as_ty(&to_ty.to_string()).to_string()); - }, - ) - }, + db.span_suggestion(e.span, "try", sugg.to_string()); + }, + ), + (&ty::TyInt(_), &ty::TyRawPtr(_)) | (&ty::TyUint(_), &ty::TyRawPtr(_)) => span_lint_and_then( + cx, + USELESS_TRANSMUTE, + e.span, + "transmute from an integer to a pointer", + |db| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { + db.span_suggestion(e.span, "try", arg.as_ty(&to_ty.to_string()).to_string()); + }, + ), (&ty::TyFloat(_), &ty::TyRef(..)) | (&ty::TyFloat(_), &ty::TyRawPtr(_)) | (&ty::TyChar, &ty::TyRef(..)) | - (&ty::TyChar, &ty::TyRawPtr(_)) => { - span_lint( - cx, - WRONG_TRANSMUTE, - e.span, - &format!("transmute from a `{}` to a pointer", from_ty), - ) - }, - (&ty::TyRawPtr(from_ptr), _) if from_ptr.ty == to_ty => { - span_lint( - cx, - CROSSPOINTER_TRANSMUTE, - e.span, - &format!( - "transmute from a type (`{}`) to the type that it points to (`{}`)", - from_ty, - to_ty - ), - ) - }, - (_, &ty::TyRawPtr(to_ptr)) if to_ptr.ty == from_ty => { - span_lint( - cx, - CROSSPOINTER_TRANSMUTE, - e.span, - &format!("transmute from a type (`{}`) to a pointer to that type (`{}`)", from_ty, to_ty), - ) - }, - (&ty::TyRawPtr(from_pty), &ty::TyRef(_, to_rty)) => { - span_lint_and_then( - cx, - TRANSMUTE_PTR_TO_REF, - e.span, - &format!( - "transmute from a pointer type (`{}`) to a reference type \ - (`{}`)", - from_ty, - to_ty - ), - |db| { - let arg = sugg::Sugg::hir(cx, &args[0], ".."); - let (deref, cast) = if to_rty.mutbl == Mutability::MutMutable { - ("&mut *", "*mut") - } else { - ("&*", "*const") - }; + (&ty::TyChar, &ty::TyRawPtr(_)) => span_lint( + cx, + WRONG_TRANSMUTE, + e.span, + &format!("transmute from a `{}` to a pointer", from_ty), + ), + (&ty::TyRawPtr(from_ptr), _) if from_ptr.ty == to_ty => span_lint( + cx, + CROSSPOINTER_TRANSMUTE, + e.span, + &format!( + "transmute from a type (`{}`) to the type that it points to (`{}`)", + from_ty, + to_ty + ), + ), + (_, &ty::TyRawPtr(to_ptr)) if to_ptr.ty == from_ty => span_lint( + cx, + CROSSPOINTER_TRANSMUTE, + e.span, + &format!("transmute from a type (`{}`) to a pointer to that type (`{}`)", from_ty, to_ty), + ), + (&ty::TyRawPtr(from_pty), &ty::TyRef(_, to_rty)) => span_lint_and_then( + cx, + TRANSMUTE_PTR_TO_REF, + e.span, + &format!( + "transmute from a pointer type (`{}`) to a reference type \ + (`{}`)", + from_ty, + to_ty + ), + |db| { + let arg = sugg::Sugg::hir(cx, &args[0], ".."); + let (deref, cast) = if to_rty.mutbl == Mutability::MutMutable { + ("&mut *", "*mut") + } else { + ("&*", "*const") + }; - let arg = if from_pty.ty == to_rty.ty { - arg - } else { - arg.as_ty(&format!("{} {}", cast, get_type_snippet(cx, qpath, to_rty.ty))) - }; + let arg = if from_pty.ty == to_rty.ty { + arg + } else { + arg.as_ty(&format!("{} {}", cast, get_type_snippet(cx, qpath, to_rty.ty))) + }; - db.span_suggestion(e.span, "try", sugg::make_unop(deref, arg).to_string()); - }, - ) - }, + db.span_suggestion(e.span, "try", sugg::make_unop(deref, arg).to_string()); + }, + ), _ => return, }; } diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 05a498ff2622..78e06fa80ddc 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -1,16 +1,16 @@ use reexport::*; use rustc::hir; use rustc::hir::*; -use rustc::hir::intravisit::{FnKind, Visitor, walk_ty, NestedVisitorMap}; +use rustc::hir::intravisit::{walk_ty, FnKind, NestedVisitorMap, Visitor}; use rustc::lint::*; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::subst::Substs; use std::cmp::Ordering; -use syntax::ast::{IntTy, UintTy, FloatTy}; +use syntax::ast::{FloatTy, IntTy, UintTy}; use syntax::attr::IntType; use syntax::codemap::Span; -use utils::{comparisons, higher, in_external_macro, in_macro, match_def_path, snippet, span_help_and_lint, span_lint, - span_lint_and_sugg, opt_def_id, last_path_segment, type_size, match_path}; +use utils::{comparisons, higher, in_external_macro, in_macro, last_path_segment, match_def_path, match_path, + opt_def_id, snippet, span_help_and_lint, span_lint, span_lint_and_sugg, type_size}; use utils::paths; /// Handles all the linting of funky types @@ -114,8 +114,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypePass { fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) { match item.node { - TraitItemKind::Const(ref ty, _) | - TraitItemKind::Type(_, Some(ref ty)) => check_ty(cx, ty, false), + TraitItemKind::Const(ref ty, _) | TraitItemKind::Type(_, Some(ref ty)) => check_ty(cx, ty, false), TraitItemKind::Method(ref sig, _) => check_fn_decl(cx, &sig.decl), _ => (), } @@ -182,20 +181,18 @@ fn check_ty(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool) { match *qpath { QPath::Resolved(Some(ref ty), ref p) => { check_ty(cx, ty, is_local); - for ty in p.segments.iter().flat_map( - |seg| seg.parameters.types.iter(), - ) + for ty in p.segments + .iter() + .flat_map(|seg| seg.parameters.types.iter()) { check_ty(cx, ty, is_local); } }, - QPath::Resolved(None, ref p) => { - for ty in p.segments.iter().flat_map( - |seg| seg.parameters.types.iter(), - ) - { - check_ty(cx, ty, is_local); - } + QPath::Resolved(None, ref p) => for ty in p.segments + .iter() + .flat_map(|seg| seg.parameters.types.iter()) + { + check_ty(cx, ty, is_local); }, QPath::TypeRelative(ref ty, ref seg) => { check_ty(cx, ty, is_local); @@ -248,13 +245,9 @@ fn check_ty(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool) { } }, // recurse - TySlice(ref ty) | - TyArray(ref ty, _) | - TyPtr(MutTy { ref ty, .. }) => check_ty(cx, ty, is_local), - TyTup(ref tys) => { - for ty in tys { - check_ty(cx, ty, is_local); - } + TySlice(ref ty) | TyArray(ref ty, _) | TyPtr(MutTy { ref ty, .. }) => check_ty(cx, ty, is_local), + TyTup(ref tys) => for ty in tys { + check_ty(cx, ty, is_local); }, _ => {}, } @@ -529,25 +522,21 @@ declare_lint! { /// Will return 0 if the type is not an int or uint variant fn int_ty_to_nbits(typ: Ty, tcx: TyCtxt) -> u64 { match typ.sty { - ty::TyInt(i) => { - match i { - IntTy::Is => tcx.data_layout.pointer_size.bits(), - IntTy::I8 => 8, - IntTy::I16 => 16, - IntTy::I32 => 32, - IntTy::I64 => 64, - IntTy::I128 => 128, - } + ty::TyInt(i) => match i { + IntTy::Is => tcx.data_layout.pointer_size.bits(), + IntTy::I8 => 8, + IntTy::I16 => 16, + IntTy::I32 => 32, + IntTy::I64 => 64, + IntTy::I128 => 128, }, - ty::TyUint(i) => { - match i { - UintTy::Us => tcx.data_layout.pointer_size.bits(), - UintTy::U8 => 8, - UintTy::U16 => 16, - UintTy::U32 => 32, - UintTy::U64 => 64, - UintTy::U128 => 128, - } + ty::TyUint(i) => match i { + UintTy::Us => tcx.data_layout.pointer_size.bits(), + UintTy::U8 => 8, + UintTy::U16 => 16, + UintTy::U32 => 32, + UintTy::U64 => 64, + UintTy::U128 => 128, }, _ => 0, } @@ -555,8 +544,7 @@ fn int_ty_to_nbits(typ: Ty, tcx: TyCtxt) -> u64 { fn is_isize_or_usize(typ: Ty) -> bool { match typ.sty { - ty::TyInt(IntTy::Is) | - ty::TyUint(UintTy::Us) => true, + ty::TyInt(IntTy::Is) | ty::TyUint(UintTy::Us) => true, _ => false, } } @@ -578,7 +566,7 @@ fn span_precision_loss_lint(cx: &LateContext, expr: &Expr, cast_from: Ty, cast_t expr.span, &format!( "casting {0} to {1} causes a loss of precision {2}({0} is {3} bits wide, but {1}'s mantissa \ - is only {4} bits wide)", + is only {4} bits wide)", cast_from, if cast_to_f64 { "f64" } else { "f32" }, if arch_dependent { @@ -617,38 +605,32 @@ fn check_truncation_and_wrapping(cx: &LateContext, expr: &Expr, cast_from: Ty, c let to_nbits = int_ty_to_nbits(cast_to, cx.tcx); let (span_truncation, suffix_truncation, span_wrap, suffix_wrap) = match (is_isize_or_usize(cast_from), is_isize_or_usize(cast_to)) { - (true, true) | (false, false) => { - ( - to_nbits < from_nbits, - ArchSuffix::None, - to_nbits == from_nbits && cast_unsigned_to_signed, - ArchSuffix::None, - ) - }, - (true, false) => { - ( - to_nbits <= 32, - if to_nbits == 32 { - ArchSuffix::_64 - } else { - ArchSuffix::None - }, - to_nbits <= 32 && cast_unsigned_to_signed, - ArchSuffix::_32, - ) - }, - (false, true) => { - ( - from_nbits == 64, - ArchSuffix::_32, - cast_unsigned_to_signed, - if from_nbits == 64 { - ArchSuffix::_64 - } else { - ArchSuffix::_32 - }, - ) - }, + (true, true) | (false, false) => ( + to_nbits < from_nbits, + ArchSuffix::None, + to_nbits == from_nbits && cast_unsigned_to_signed, + ArchSuffix::None, + ), + (true, false) => ( + to_nbits <= 32, + if to_nbits == 32 { + ArchSuffix::_64 + } else { + ArchSuffix::None + }, + to_nbits <= 32 && cast_unsigned_to_signed, + ArchSuffix::_32, + ), + (false, true) => ( + from_nbits == 64, + ArchSuffix::_32, + cast_unsigned_to_signed, + if from_nbits == 64 { + ArchSuffix::_64 + } else { + ArchSuffix::_32 + }, + ), }; if span_truncation { span_lint( @@ -690,8 +672,7 @@ fn check_lossless(cx: &LateContext, expr: &Expr, op: &Expr, cast_from: Ty, cast_ let cast_signed_to_unsigned = cast_from.is_signed() && !cast_to.is_signed(); let from_nbits = int_ty_to_nbits(cast_from, cx.tcx); let to_nbits = int_ty_to_nbits(cast_to, cx.tcx); - if !is_isize_or_usize(cast_from) && !is_isize_or_usize(cast_to) && from_nbits < to_nbits && - !cast_signed_to_unsigned + if !is_isize_or_usize(cast_from) && !is_isize_or_usize(cast_to) && from_nbits < to_nbits && !cast_signed_to_unsigned { span_lossless_lint(cx, expr, op, cast_from, cast_to); } @@ -715,19 +696,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { if let ExprCast(ref ex, _) = expr.node { let (cast_from, cast_to) = (cx.tables.expr_ty(ex), cx.tables.expr_ty(expr)); if let ExprLit(ref lit) = ex.node { - use syntax::ast::{LitKind, LitIntType}; + use syntax::ast::{LitIntType, LitKind}; match lit.node { - LitKind::Int(_, LitIntType::Unsuffixed) | - LitKind::FloatUnsuffixed(_) => {}, - _ => { - if cast_from.sty == cast_to.sty && !in_external_macro(cx, expr.span) { - span_lint( - cx, - UNNECESSARY_CAST, - expr.span, - &format!("casting to the same type is unnecessary (`{}` -> `{}`)", cast_from, cast_to), - ); - } + LitKind::Int(_, LitIntType::Unsuffixed) | LitKind::FloatUnsuffixed(_) => {}, + _ => if cast_from.sty == cast_to.sty && !in_external_macro(cx, expr.span) { + span_lint( + cx, + UNNECESSARY_CAST, + expr.span, + &format!("casting to the same type is unnecessary (`{}` -> `{}`)", cast_from, cast_to), + ); }, } } @@ -776,8 +754,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { check_lossless(cx, expr, ex, cast_from, cast_to); }, (false, false) => { - if let (&ty::TyFloat(FloatTy::F64), &ty::TyFloat(FloatTy::F32)) = - (&cast_from.sty, &cast_to.sty) + if let (&ty::TyFloat(FloatTy::F64), &ty::TyFloat(FloatTy::F32)) = (&cast_from.sty, &cast_to.sty) { span_lint( cx, @@ -786,8 +763,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { "casting f64 to f32 may truncate the value", ); } - if let (&ty::TyFloat(FloatTy::F32), &ty::TyFloat(FloatTy::F64)) = - (&cast_from.sty, &cast_to.sty) + if let (&ty::TyFloat(FloatTy::F32), &ty::TyFloat(FloatTy::F64)) = (&cast_from.sty, &cast_to.sty) { span_lossless_lint(cx, expr, ex, cast_from, cast_to); } @@ -823,7 +799,9 @@ pub struct TypeComplexityPass { impl TypeComplexityPass { pub fn new(threshold: u64) -> Self { - Self { threshold: threshold } + Self { + threshold: threshold, + } } } @@ -853,8 +831,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeComplexityPass { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { match item.node { - ItemStatic(ref ty, _, _) | - ItemConst(ref ty, _) => self.check_type(cx, ty), + ItemStatic(ref ty, _, _) | ItemConst(ref ty, _) => self.check_type(cx, ty), // functions, enums, structs, impls and traits are covered _ => (), } @@ -862,8 +839,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeComplexityPass { fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem) { match item.node { - TraitItemKind::Const(ref ty, _) | - TraitItemKind::Type(_, Some(ref ty)) => self.check_type(cx, ty), + TraitItemKind::Const(ref ty, _) | TraitItemKind::Type(_, Some(ref ty)) => self.check_type(cx, ty), TraitItemKind::Method(MethodSig { ref decl, .. }, TraitMethod::Required(_)) => self.check_fndecl(cx, decl), // methods with default impl are covered by check_fn _ => (), @@ -872,8 +848,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeComplexityPass { fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx ImplItem) { match item.node { - ImplItemKind::Const(ref ty, _) | - ImplItemKind::Type(ref ty) => self.check_type(cx, ty), + ImplItemKind::Const(ref ty, _) | ImplItemKind::Type(ref ty) => self.check_type(cx, ty), // methods are covered by check_fn _ => (), } @@ -938,9 +913,9 @@ impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor { TyBareFn(..) => (50 * self.nest, 1), TyTraitObject(ref param_bounds, _) => { - let has_lifetime_parameters = param_bounds.iter().any( - |bound| !bound.bound_lifetimes.is_empty(), - ); + let has_lifetime_parameters = param_bounds + .iter() + .any(|bound| !bound.bound_lifetimes.is_empty()); if has_lifetime_parameters { // complex trait bounds like A<'a, 'b> (50 * self.nest, 1) @@ -1101,7 +1076,7 @@ fn detect_absurd_comparison<'a>( Rel::Le => { match (lx, rx) { (Some(l @ ExtremeExpr { which: Minimum, .. }), _) => (l, AlwaysTrue), // min <= x - (Some(l @ ExtremeExpr { which: Maximum, .. }), _) => (l, InequalityImpossible), //max <= x + (Some(l @ ExtremeExpr { which: Maximum, .. }), _) => (l, InequalityImpossible), // max <= x (_, Some(r @ ExtremeExpr { which: Minimum, .. })) => (r, InequalityImpossible), // x <= min (_, Some(r @ ExtremeExpr { which: Maximum, .. })) => (r, AlwaysTrue), // x <= max _ => return None, @@ -1187,14 +1162,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AbsurdExtremeComparisons { let conclusion = match result { AlwaysFalse => "this comparison is always false".to_owned(), AlwaysTrue => "this comparison is always true".to_owned(), - InequalityImpossible => { - format!( - "the case where the two sides are not equal never occurs, consider using {} == {} \ - instead", - snippet(cx, lhs.span, "lhs"), - snippet(cx, rhs.span, "rhs") - ) - }, + InequalityImpossible => format!( + "the case where the two sides are not equal never occurs, consider using {} == {} \ + instead", + snippet(cx, lhs.span, "lhs"), + snippet(cx, rhs.span, "rhs") + ), }; let help = format!( @@ -1264,9 +1237,8 @@ impl FullInt { impl PartialEq for FullInt { fn eq(&self, other: &Self) -> bool { - self.partial_cmp(other).expect( - "partial_cmp only returns Some(_)", - ) == Ordering::Equal + self.partial_cmp(other) + .expect("partial_cmp only returns Some(_)") == Ordering::Equal } } @@ -1282,9 +1254,8 @@ impl PartialOrd for FullInt { } impl Ord for FullInt { fn cmp(&self, other: &Self) -> Ordering { - self.partial_cmp(other).expect( - "partial_cmp for FullInt can never return None", - ) + self.partial_cmp(other) + .expect("partial_cmp for FullInt can never return None") } } @@ -1301,44 +1272,40 @@ fn numeric_cast_precast_bounds<'a>(cx: &LateContext, expr: &'a Expr) -> Option<( return None; } match pre_cast_ty.sty { - ty::TyInt(int_ty) => { - Some(match int_ty { - IntTy::I8 => (FullInt::S(i128::from(i8::min_value())), FullInt::S(i128::from(i8::max_value()))), - IntTy::I16 => ( - FullInt::S(i128::from(i16::min_value())), - FullInt::S(i128::from(i16::max_value())), - ), - IntTy::I32 => ( - FullInt::S(i128::from(i32::min_value())), - FullInt::S(i128::from(i32::max_value())), - ), - IntTy::I64 => ( - FullInt::S(i128::from(i64::min_value())), - FullInt::S(i128::from(i64::max_value())), - ), - IntTy::I128 => (FullInt::S(i128::min_value() as i128), FullInt::S(i128::max_value() as i128)), - IntTy::Is => (FullInt::S(isize::min_value() as i128), FullInt::S(isize::max_value() as i128)), - }) - }, - ty::TyUint(uint_ty) => { - Some(match uint_ty { - UintTy::U8 => (FullInt::U(u128::from(u8::min_value())), FullInt::U(u128::from(u8::max_value()))), - UintTy::U16 => ( - FullInt::U(u128::from(u16::min_value())), - FullInt::U(u128::from(u16::max_value())), - ), - UintTy::U32 => ( - FullInt::U(u128::from(u32::min_value())), - FullInt::U(u128::from(u32::max_value())), - ), - UintTy::U64 => ( - FullInt::U(u128::from(u64::min_value())), - FullInt::U(u128::from(u64::max_value())), - ), - UintTy::U128 => (FullInt::U(u128::min_value() as u128), FullInt::U(u128::max_value() as u128)), - UintTy::Us => (FullInt::U(usize::min_value() as u128), FullInt::U(usize::max_value() as u128)), - }) - }, + ty::TyInt(int_ty) => Some(match int_ty { + IntTy::I8 => (FullInt::S(i128::from(i8::min_value())), FullInt::S(i128::from(i8::max_value()))), + IntTy::I16 => ( + FullInt::S(i128::from(i16::min_value())), + FullInt::S(i128::from(i16::max_value())), + ), + IntTy::I32 => ( + FullInt::S(i128::from(i32::min_value())), + FullInt::S(i128::from(i32::max_value())), + ), + IntTy::I64 => ( + FullInt::S(i128::from(i64::min_value())), + FullInt::S(i128::from(i64::max_value())), + ), + IntTy::I128 => (FullInt::S(i128::min_value() as i128), FullInt::S(i128::max_value() as i128)), + IntTy::Is => (FullInt::S(isize::min_value() as i128), FullInt::S(isize::max_value() as i128)), + }), + ty::TyUint(uint_ty) => Some(match uint_ty { + UintTy::U8 => (FullInt::U(u128::from(u8::min_value())), FullInt::U(u128::from(u8::max_value()))), + UintTy::U16 => ( + FullInt::U(u128::from(u16::min_value())), + FullInt::U(u128::from(u16::max_value())), + ), + UintTy::U32 => ( + FullInt::U(u128::from(u32::min_value())), + FullInt::U(u128::from(u32::max_value())), + ), + UintTy::U64 => ( + FullInt::U(u128::from(u64::min_value())), + FullInt::U(u128::from(u64::max_value())), + ), + UintTy::U128 => (FullInt::U(u128::min_value() as u128), FullInt::U(u128::max_value() as u128)), + UintTy::Us => (FullInt::U(usize::min_value() as u128), FullInt::U(usize::max_value() as u128)), + }), _ => None, } } else { @@ -1355,15 +1322,13 @@ fn node_as_const_fullint(cx: &LateContext, expr: &Expr) -> Option { let parent_def_id = cx.tcx.hir.local_def_id(parent_item); let substs = Substs::identity_for_item(cx.tcx, parent_def_id); match ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables).eval(expr) { - Ok(val) => { - if let Integral(const_int) = val { - match const_int.int_type() { - IntType::SignedInt(_) => Some(FullInt::S(const_int.to_u128_unchecked() as i128)), - IntType::UnsignedInt(_) => Some(FullInt::U(const_int.to_u128_unchecked())), - } - } else { - None + Ok(val) => if let Integral(const_int) = val { + match const_int.int_type() { + IntType::SignedInt(_) => Some(FullInt::S(const_int.to_u128_unchecked() as i128)), + IntType::UnsignedInt(_) => Some(FullInt::U(const_int.to_u128_unchecked())), } + } else { + None }, Err(_) => None, } @@ -1402,42 +1367,32 @@ fn upcast_comparison_bounds_err( err_upcast_comparison(cx, span, lhs, rel == Rel::Ne); } } else if match rel { - Rel::Lt => { - if invert { - norm_rhs_val < lb - } else { - ub < norm_rhs_val - } - }, - Rel::Le => { - if invert { - norm_rhs_val <= lb - } else { - ub <= norm_rhs_val - } - }, - Rel::Eq | Rel::Ne => unreachable!(), - } - { + Rel::Lt => if invert { + norm_rhs_val < lb + } else { + ub < norm_rhs_val + }, + Rel::Le => if invert { + norm_rhs_val <= lb + } else { + ub <= norm_rhs_val + }, + Rel::Eq | Rel::Ne => unreachable!(), + } { err_upcast_comparison(cx, span, lhs, true) } else if match rel { - Rel::Lt => { - if invert { - norm_rhs_val >= ub - } else { - lb >= norm_rhs_val - } - }, - Rel::Le => { - if invert { - norm_rhs_val > ub - } else { - lb > norm_rhs_val - } - }, - Rel::Eq | Rel::Ne => unreachable!(), - } - { + Rel::Lt => if invert { + norm_rhs_val >= ub + } else { + lb >= norm_rhs_val + }, + Rel::Le => if invert { + norm_rhs_val > ub + } else { + lb > norm_rhs_val + }, + Rel::Eq | Rel::Ne => unreachable!(), + } { err_upcast_comparison(cx, span, lhs, false) } } @@ -1447,7 +1402,6 @@ fn upcast_comparison_bounds_err( impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidUpcastComparisons { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if let ExprBinary(ref cmp, ref lhs, ref rhs) = expr.node { - let normalized = comparisons::normalize_comparison(cmp.node, lhs, rhs); let (rel, normalized_lhs, normalized_rhs) = if let Some(val) = normalized { val diff --git a/clippy_lints/src/unicode.rs b/clippy_lints/src/unicode.rs index 14d6323de47b..c045c870810b 100644 --- a/clippy_lints/src/unicode.rs +++ b/clippy_lints/src/unicode.rs @@ -3,7 +3,7 @@ use rustc::hir::*; use syntax::ast::{LitKind, NodeId}; use syntax::codemap::Span; use unicode_normalization::UnicodeNormalization; -use utils::{snippet, span_help_and_lint, is_allowed}; +use utils::{is_allowed, snippet, span_help_and_lint}; /// **What it does:** Checks for the Unicode zero-width space in the code. /// diff --git a/clippy_lints/src/unsafe_removed_from_name.rs b/clippy_lints/src/unsafe_removed_from_name.rs index 036e6f0f0e68..1c9bf70429d9 100644 --- a/clippy_lints/src/unsafe_removed_from_name.rs +++ b/clippy_lints/src/unsafe_removed_from_name.rs @@ -48,13 +48,11 @@ impl EarlyLintPass for UnsafeNameRemoval { &item.span, ); }, - ViewPath_::ViewPathList(_, ref path_list_items) => { - for path_list_item in path_list_items.iter() { - let plid = path_list_item.node; - if let Some(rename) = plid.rename { - unsafe_to_safe_check(plid.name, rename, cx, &item.span); - }; - } + ViewPath_::ViewPathList(_, ref path_list_items) => for path_list_item in path_list_items.iter() { + let plid = path_list_item.node; + if let Some(rename) = plid.rename { + unsafe_to_safe_check(plid.name, rename, cx, &item.span); + }; }, ViewPath_::ViewPathGlob(_) => {}, } diff --git a/clippy_lints/src/unused_io_amount.rs b/clippy_lints/src/unused_io_amount.rs index 1ac775ce7c19..1af63c56107d 100644 --- a/clippy_lints/src/unused_io_amount.rs +++ b/clippy_lints/src/unused_io_amount.rs @@ -1,6 +1,6 @@ use rustc::lint::*; use rustc::hir; -use utils::{span_lint, match_qpath, match_trait_method, is_try, paths}; +use utils::{is_try, match_qpath, match_trait_method, paths, span_lint}; /// **What it does:** Checks for unused written/read amount. /// @@ -40,8 +40,7 @@ impl LintPass for UnusedIoAmount { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedIoAmount { fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) { let expr = match s.node { - hir::StmtSemi(ref expr, _) | - hir::StmtExpr(ref expr, _) => &**expr, + hir::StmtSemi(ref expr, _) | hir::StmtExpr(ref expr, _) => &**expr, _ => return, }; @@ -58,13 +57,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedIoAmount { } }, - hir::ExprMethodCall(ref path, _, ref args) => { - match &*path.name.as_str() { - "expect" | "unwrap" | "unwrap_or" | "unwrap_or_else" => { - check_method_call(cx, &args[0], expr); - }, - _ => (), - } + hir::ExprMethodCall(ref path, _, ref args) => match &*path.name.as_str() { + "expect" | "unwrap" | "unwrap_or" | "unwrap_or_else" => { + check_method_call(cx, &args[0], expr); + }, + _ => (), }, _ => (), diff --git a/clippy_lints/src/unused_label.rs b/clippy_lints/src/unused_label.rs index 8a8afe8a377c..6f91b873a480 100644 --- a/clippy_lints/src/unused_label.rs +++ b/clippy_lints/src/unused_label.rs @@ -1,6 +1,6 @@ use rustc::lint::*; use rustc::hir; -use rustc::hir::intravisit::{FnKind, Visitor, walk_expr, walk_fn, NestedVisitorMap}; +use rustc::hir::intravisit::{walk_expr, walk_fn, FnKind, NestedVisitorMap, Visitor}; use std::collections::HashMap; use syntax::ast; use syntax::codemap::Span; @@ -69,14 +69,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedLabel { impl<'a, 'tcx: 'a> Visitor<'tcx> for UnusedLabelVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx hir::Expr) { match expr.node { - hir::ExprBreak(destination, _) | - hir::ExprAgain(destination) => { - if let Some(label) = destination.ident { - self.labels.remove(&label.node.name.as_str()); - } + hir::ExprBreak(destination, _) | hir::ExprAgain(destination) => if let Some(label) = destination.ident { + self.labels.remove(&label.node.name.as_str()); }, - hir::ExprLoop(_, Some(label), _) | - hir::ExprWhile(_, _, Some(label)) => { + hir::ExprLoop(_, Some(label), _) | hir::ExprWhile(_, _, Some(label)) => { self.labels.insert(label.node.as_str(), expr.span); }, _ => (), diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 9f75ed2717b2..bb5f6075d0da 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -1,7 +1,7 @@ -use rustc::lint::{LintArray, LateLintPass, LateContext, LintPass}; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::hir::*; -use rustc::hir::intravisit::{Visitor, walk_path, NestedVisitorMap}; -use utils::{span_lint_and_then, in_macro}; +use rustc::hir::intravisit::{walk_path, NestedVisitorMap, Visitor}; +use utils::{in_macro, span_lint_and_then}; use syntax::ast::NodeId; use syntax_pos::symbol::keywords::SelfType; diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index dfac7366553c..fafb6d12d1fd 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -5,9 +5,9 @@ use rustc::lint::*; use rustc::hir; -use rustc::hir::{Expr, QPath, Expr_}; -use rustc::hir::intravisit::{Visitor, NestedVisitorMap}; -use syntax::ast::{self, Attribute, NodeId, LitKind, DUMMY_NODE_ID}; +use rustc::hir::{Expr, Expr_, QPath}; +use rustc::hir::intravisit::{NestedVisitorMap, Visitor}; +use syntax::ast::{self, Attribute, LitKind, NodeId, DUMMY_NODE_ID}; use syntax::codemap::Span; use std::collections::HashMap; @@ -386,15 +386,13 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { println!("Again(ref {}) = {},", destination_pat, current); // FIXME: implement label printing }, - Expr_::ExprRet(ref opt_value) => { - if let Some(ref value) = *opt_value { - let value_pat = self.next("value"); - println!("Ret(Some(ref {})) = {},", value_pat, current); - self.current = value_pat; - self.visit_expr(value); - } else { - println!("Ret(None) = {},", current); - } + Expr_::ExprRet(ref opt_value) => if let Some(ref value) = *opt_value { + let value_pat = self.next("value"); + println!("Ret(Some(ref {})) = {},", value_pat, current); + self.current = value_pat; + self.visit_expr(value); + } else { + println!("Ret(None) = {},", current); }, Expr_::ExprInlineAsm(_, ref _input, ref _output) => { println!("InlineAsm(_, ref input, ref output) = {},", current); @@ -445,42 +443,36 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { fn has_attr(attrs: &[Attribute]) -> bool { attrs.iter().any(|attr| { - attr.check_name("clippy") && - attr.meta_item_list().map_or(false, |list| { - list.len() == 1 && - match list[0].node { - ast::NestedMetaItemKind::MetaItem(ref it) => it.name == "author", - ast::NestedMetaItemKind::Literal(_) => false, - } - }) + attr.check_name("clippy") && attr.meta_item_list().map_or(false, |list| { + list.len() == 1 && match list[0].node { + ast::NestedMetaItemKind::MetaItem(ref it) => it.name == "author", + ast::NestedMetaItemKind::Literal(_) => false, + } + }) }) } fn print_path(path: &QPath, first: &mut bool) { match *path { - QPath::Resolved(_, ref path) => { - for segment in &path.segments { + QPath::Resolved(_, ref path) => for segment in &path.segments { + if *first { + *first = false; + } else { + print!(", "); + } + print!("{:?}", segment.name.as_str()); + }, + QPath::TypeRelative(ref ty, ref segment) => match ty.node { + hir::Ty_::TyPath(ref inner_path) => { + print_path(inner_path, first); if *first { *first = false; } else { print!(", "); } print!("{:?}", segment.name.as_str()); - } - }, - QPath::TypeRelative(ref ty, ref segment) => { - match ty.node { - hir::Ty_::TyPath(ref inner_path) => { - print_path(inner_path, first); - if *first { - *first = false; - } else { - print!(", "); - } - print!("{:?}", segment.name.as_str()); - }, - ref other => print!("/* unimplemented: {:?}*/", other), - } + }, + ref other => print!("/* unimplemented: {:?}*/", other), }, } } diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index ad9e7e201768..7251538c09aa 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -15,14 +15,13 @@ pub fn file_from_args( for arg in args.iter().filter_map(|a| a.meta_item()) { if arg.name() == "conf_file" { return match arg.node { - ast::MetaItemKind::Word | - ast::MetaItemKind::List(_) => Err(("`conf_file` must be a named value", arg.span)), - ast::MetaItemKind::NameValue(ref value) => { - if let ast::LitKind::Str(ref file, _) = value.node { - Ok(Some(file.to_string().into())) - } else { - Err(("`conf_file` value must be a string", value.span)) - } + ast::MetaItemKind::Word | ast::MetaItemKind::List(_) => { + Err(("`conf_file` must be a named value", arg.span)) + }, + ast::MetaItemKind::NameValue(ref value) => if let ast::LitKind::Str(ref file, _) = value.node { + Ok(Some(file.to_string().into())) + } else { + Err(("`conf_file` value must be a string", value.span)) }, }; } @@ -45,7 +44,7 @@ pub enum Error { /// The expected type. &'static str, /// The type we got instead. - &'static str + &'static str, ), /// There is an unknown key is the file. UnknownKey(String), @@ -191,10 +190,8 @@ pub fn lookup_conf_file() -> io::Result> { Ok(ref md) if md.is_file() => return Ok(Some(config_file)), // Return the error if it's something other than `NotFound`; otherwise we didn't // find the project file yet, and continue searching. - Err(e) => { - if e.kind() != io::ErrorKind::NotFound { - return Err(e); - } + Err(e) => if e.kind() != io::ErrorKind::NotFound { + return Err(e); }, _ => (), } diff --git a/clippy_lints/src/utils/higher.rs b/clippy_lints/src/utils/higher.rs index d9a454aaf7e3..09e40aea80de 100644 --- a/clippy_lints/src/utils/higher.rs +++ b/clippy_lints/src/utils/higher.rs @@ -6,7 +6,7 @@ use rustc::hir; use rustc::lint::LateContext; use syntax::ast; -use utils::{is_expn_of, match_qpath, match_def_path, resolve_node, paths}; +use utils::{is_expn_of, match_def_path, match_qpath, paths, resolve_node}; /// Convert a hir binary operator to the corresponding `ast` type. pub fn binop(op: hir::BinOp_) -> ast::BinOpKind { @@ -73,42 +73,40 @@ pub fn range(expr: &hir::Expr) -> Option { None } }, - hir::ExprStruct(ref path, ref fields, None) => { - if match_qpath(path, &paths::RANGE_FROM_STD) || match_qpath(path, &paths::RANGE_FROM) { - Some(Range { - start: get_field("start", fields), - end: None, - limits: ast::RangeLimits::HalfOpen, - }) - } else if match_qpath(path, &paths::RANGE_INCLUSIVE_STD) || match_qpath(path, &paths::RANGE_INCLUSIVE) { - Some(Range { - start: get_field("start", fields), - end: get_field("end", fields), - limits: ast::RangeLimits::Closed, - }) - } else if match_qpath(path, &paths::RANGE_STD) || match_qpath(path, &paths::RANGE) { - Some(Range { - start: get_field("start", fields), - end: get_field("end", fields), - limits: ast::RangeLimits::HalfOpen, - }) - } else if match_qpath(path, &paths::RANGE_TO_INCLUSIVE_STD) || - match_qpath(path, &paths::RANGE_TO_INCLUSIVE) - { - Some(Range { - start: None, - end: get_field("end", fields), - limits: ast::RangeLimits::Closed, - }) - } else if match_qpath(path, &paths::RANGE_TO_STD) || match_qpath(path, &paths::RANGE_TO) { - Some(Range { - start: None, - end: get_field("end", fields), - limits: ast::RangeLimits::HalfOpen, - }) - } else { - None - } + hir::ExprStruct(ref path, ref fields, None) => if match_qpath(path, &paths::RANGE_FROM_STD) || + match_qpath(path, &paths::RANGE_FROM) + { + Some(Range { + start: get_field("start", fields), + end: None, + limits: ast::RangeLimits::HalfOpen, + }) + } else if match_qpath(path, &paths::RANGE_INCLUSIVE_STD) || match_qpath(path, &paths::RANGE_INCLUSIVE) { + Some(Range { + start: get_field("start", fields), + end: get_field("end", fields), + limits: ast::RangeLimits::Closed, + }) + } else if match_qpath(path, &paths::RANGE_STD) || match_qpath(path, &paths::RANGE) { + Some(Range { + start: get_field("start", fields), + end: get_field("end", fields), + limits: ast::RangeLimits::HalfOpen, + }) + } else if match_qpath(path, &paths::RANGE_TO_INCLUSIVE_STD) || match_qpath(path, &paths::RANGE_TO_INCLUSIVE) { + Some(Range { + start: None, + end: get_field("end", fields), + limits: ast::RangeLimits::Closed, + }) + } else if match_qpath(path, &paths::RANGE_TO_STD) || match_qpath(path, &paths::RANGE_TO) { + Some(Range { + start: None, + end: get_field("end", fields), + limits: ast::RangeLimits::HalfOpen, + }) + } else { + None }, _ => None, } diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 0b3f409adf44..2d3d5874d821 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -46,8 +46,9 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { false } }, - (&StmtExpr(ref l, _), &StmtExpr(ref r, _)) | - (&StmtSemi(ref l, _), &StmtSemi(ref r, _)) => self.eq_expr(l, r), + (&StmtExpr(ref l, _), &StmtExpr(ref r, _)) | (&StmtSemi(ref l, _), &StmtSemi(ref r, _)) => { + self.eq_expr(l, r) + }, _ => false, } } @@ -107,11 +108,10 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { lls == rls && self.eq_block(lb, rb) && both(ll, rl, |l, r| l.node.as_str() == r.node.as_str()) }, (&ExprMatch(ref le, ref la, ref ls), &ExprMatch(ref re, ref ra, ref rs)) => { - ls == rs && self.eq_expr(le, re) && - over(la, ra, |l, r| { - self.eq_expr(&l.body, &r.body) && both(&l.guard, &r.guard, |l, r| self.eq_expr(l, r)) && - over(&l.pats, &r.pats, |l, r| self.eq_pat(l, r)) - }) + ls == rs && self.eq_expr(le, re) && over(la, ra, |l, r| { + self.eq_expr(&l.body, &r.body) && both(&l.guard, &r.guard, |l, r| self.eq_expr(l, r)) && + over(&l.pats, &r.pats, |l, r| self.eq_pat(l, r)) + }) }, (&ExprMethodCall(ref l_path, _, ref l_args), &ExprMethodCall(ref r_path, _, ref r_args)) => { !self.ignore_fn && l_path == r_path && self.eq_exprs(l_args, r_args) @@ -257,9 +257,8 @@ fn both(l: &Option, r: &Option, mut eq_fn: F) -> bool where F: FnMut(&X, &X) -> bool, { - l.as_ref().map_or_else(|| r.is_none(), |x| { - r.as_ref().map_or(false, |y| eq_fn(x, y)) - }) + l.as_ref() + .map_or_else(|| r.is_none(), |x| r.as_ref().map_or(false, |y| eq_fn(x, y))) } /// Check if two slices are equal as per `eq_fn`. diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index 315f49870711..cdc8ce509b45 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -54,12 +54,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { match item.vis { hir::Visibility::Public => println!("public"), hir::Visibility::Crate => println!("visible crate wide"), - hir::Visibility::Restricted { ref path, .. } => { - println!( - "visible in module `{}`", - print::to_string(print::NO_ANN, |s| s.print_path(path, false)) - ) - }, + hir::Visibility::Restricted { ref path, .. } => println!( + "visible in module `{}`", + print::to_string(print::NO_ANN, |s| s.print_path(path, false)) + ), hir::Visibility::Inherited => println!("visibility inherited from outer item"), } if item.defaultness.is_default() { @@ -125,8 +123,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } match stmt.node { hir::StmtDecl(ref decl, _) => print_decl(cx, decl), - hir::StmtExpr(ref e, _) | - hir::StmtSemi(ref e, _) => print_expr(cx, e, 0), + hir::StmtExpr(ref e, _) | hir::StmtSemi(ref e, _) => print_expr(cx, e, 0), } } // fn check_foreign_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx @@ -355,12 +352,10 @@ fn print_item(cx: &LateContext, item: &hir::Item) { match item.vis { hir::Visibility::Public => println!("public"), hir::Visibility::Crate => println!("visible crate wide"), - hir::Visibility::Restricted { ref path, .. } => { - println!( - "visible in module `{}`", - print::to_string(print::NO_ANN, |s| s.print_path(path, false)) - ) - }, + hir::Visibility::Restricted { ref path, .. } => println!( + "visible in module `{}`", + print::to_string(print::NO_ANN, |s| s.print_path(path, false)) + ), hir::Visibility::Inherited => println!("visibility inherited from outer item"), } match item.node { diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index a2832ef7af23..a35b034d791b 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -1,11 +1,11 @@ use rustc::lint::*; use rustc::hir::*; -use rustc::hir::intravisit::{Visitor, walk_expr, NestedVisitorMap}; -use utils::{paths, match_qpath, span_lint}; +use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; +use utils::{match_qpath, paths, span_lint}; use syntax::symbol::InternedString; -use syntax::ast::{Name, NodeId, ItemKind, Crate as AstCrate}; +use syntax::ast::{Crate as AstCrate, ItemKind, Name, NodeId}; use syntax::codemap::Span; -use std::collections::{HashSet, HashMap}; +use std::collections::{HashMap, HashSet}; /// **What it does:** Checks for various things we like to keep tidy in clippy. @@ -63,14 +63,17 @@ impl LintPass for Clippy { impl EarlyLintPass for Clippy { 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 Some(utils) = krate + .module + .items + .iter() + .find(|item| item.ident.name == "utils") { if let ItemKind::Mod(ref utils_mod) = utils.node { - if let Some(paths) = utils_mod.items.iter().find( - |item| item.ident.name == "paths", - ) + if let Some(paths) = utils_mod + .items + .iter() + .find(|item| item.ident.name == "paths") { if let ItemKind::Mod(ref paths_mod) = paths.node { let mut last_name: Option = None; @@ -83,7 +86,7 @@ impl EarlyLintPass for Clippy { CLIPPY_LINTS_INTERNAL, item.span, "this constant should be before the previous constant due to lexical \ - ordering", + ordering", ); } } @@ -157,11 +160,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LintWithoutLintPass { fn is_lint_ref_type(ty: &Ty) -> bool { - if let TyRptr(ref lt, - MutTy { - ty: ref inner, - mutbl: MutImmutable, - }) = ty.node + if let TyRptr( + ref lt, + MutTy { + ty: ref inner, + mutbl: MutImmutable, + }, + ) = ty.node { if lt.is_elided() { return false; diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 8828a32512b9..29fddeaa052f 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -5,10 +5,10 @@ use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX}; use rustc::hir::def::Def; use rustc::hir::intravisit::{NestedVisitorMap, Visitor}; use rustc::hir::map::Node; -use rustc::lint::{LintContext, Level, LateContext, Lint}; +use rustc::lint::{LateContext, Level, Lint, LintContext}; use rustc::session::Session; use rustc::traits; -use rustc::ty::{self, TyCtxt, Ty}; +use rustc::ty::{self, Ty, TyCtxt}; use rustc::mir::transform::MirSource; use rustc_errors; use std::borrow::Cow; @@ -104,18 +104,16 @@ pub fn differing_macro_contexts(lhs: Span, rhs: Span) -> bool { pub fn in_constant(cx: &LateContext, id: NodeId) -> bool { let parent_id = cx.tcx.hir.get_parent(id); match MirSource::from_node(cx.tcx, parent_id) { - MirSource::GeneratorDrop(_) | - MirSource::Fn(_) => false, - MirSource::Const(_) | - MirSource::Static(..) | - MirSource::Promoted(..) => true, + MirSource::GeneratorDrop(_) | MirSource::Fn(_) => false, + MirSource::Const(_) | MirSource::Static(..) | MirSource::Promoted(..) => true, } } /// Returns true if this `expn_info` was expanded by any macro. pub fn in_macro(span: Span) -> bool { span.ctxt().outer().expn_info().map_or(false, |info| { - match info.callee.format {// don't treat range expressions desugared to structs as "in_macro" + match info.callee.format { + // don't treat range expressions desugared to structs as "in_macro" ExpnFormat::CompilerDesugaring(kind) => kind != CompilerDesugaringKind::DotFill, _ => true, } @@ -138,18 +136,18 @@ pub fn in_external_macro<'a, T: LintContext<'a>>(cx: &T, span: Span) -> bool { // no span for the callee = external macro info.callee.span.map_or(true, |span| { // no snippet = external macro or compiler-builtin expansion - cx.sess().codemap().span_to_snippet(span).ok().map_or( - true, - |code| { - !code.starts_with("macro_rules") - }, - ) + cx.sess() + .codemap() + .span_to_snippet(span) + .ok() + .map_or(true, |code| !code.starts_with("macro_rules")) }) } - span.ctxt().outer().expn_info().map_or(false, |info| { - in_macro_ext(cx, &info) - }) + span.ctxt() + .outer() + .expn_info() + .map_or(false, |info| in_macro_ext(cx, &info)) } /// Check if a `DefId`'s path matches the given absolute type path usage. @@ -183,9 +181,10 @@ pub fn match_def_path(tcx: TyCtxt, def_id: DefId, path: &[&str]) -> bool { tcx.push_item_path(&mut apb, def_id); apb.names.len() == path.len() && - apb.names.into_iter().zip(path.iter()).all( - |(a, &b)| *a == *b, - ) + apb.names + .into_iter() + .zip(path.iter()) + .all(|(a, &b)| *a == *b) } /// Check if type is struct, enum or union type with given def path. @@ -220,11 +219,9 @@ pub fn match_trait_method(cx: &LateContext, expr: &Expr, path: &[&str]) -> bool pub fn last_path_segment(path: &QPath) -> &PathSegment { match *path { - QPath::Resolved(_, ref path) => { - path.segments.last().expect( - "A path must have at least one segment", - ) - }, + QPath::Resolved(_, ref path) => path.segments + .last() + .expect("A path must have at least one segment"), QPath::TypeRelative(_, ref seg) => seg, } } @@ -246,22 +243,22 @@ pub fn single_segment_path(path: &QPath) -> Option<&PathSegment> { pub fn match_qpath(path: &QPath, segments: &[&str]) -> bool { match *path { QPath::Resolved(_, ref path) => match_path(path, segments), - QPath::TypeRelative(ref ty, ref segment) => { - match ty.node { - TyPath(ref inner_path) => { - !segments.is_empty() && match_qpath(inner_path, &segments[..(segments.len() - 1)]) && - segment.name == segments[segments.len() - 1] - }, - _ => false, - } + QPath::TypeRelative(ref ty, ref segment) => match ty.node { + TyPath(ref inner_path) => { + !segments.is_empty() && match_qpath(inner_path, &segments[..(segments.len() - 1)]) && + segment.name == segments[segments.len() - 1] + }, + _ => false, }, } } pub fn match_path(path: &Path, segments: &[&str]) -> bool { - path.segments.iter().rev().zip(segments.iter().rev()).all( - |(a, b)| a.name == *b, - ) + path.segments + .iter() + .rev() + .zip(segments.iter().rev()) + .all(|(a, b)| a.name == *b) } /// Match a `Path` against a slice of segment string literals, e.g. @@ -271,9 +268,11 @@ pub fn match_path(path: &Path, segments: &[&str]) -> bool { /// match_qpath(path, &["std", "rt", "begin_unwind"]) /// ``` pub fn match_path_ast(path: &ast::Path, segments: &[&str]) -> bool { - path.segments.iter().rev().zip(segments.iter().rev()).all( - |(a, b)| a.identifier.name == *b, - ) + path.segments + .iter() + .rev() + .zip(segments.iter().rev()) + .all(|(a, b)| a.identifier.name == *b) } /// Get the definition associated to a path. @@ -281,9 +280,9 @@ pub fn path_to_def(cx: &LateContext, path: &[&str]) -> Option { let cstore = &cx.tcx.sess.cstore; let crates = cstore.crates(); - let krate = crates.iter().find( - |&&krate| cstore.crate_name(krate) == path[0], - ); + let krate = crates + .iter() + .find(|&&krate| cstore.crate_name(krate) == path[0]); if let Some(krate) = krate { let krate = DefId { krate: *krate, @@ -336,14 +335,9 @@ pub fn implements_trait<'a, 'tcx>( ty_params: &[Ty<'tcx>], ) -> bool { let ty = cx.tcx.erase_regions(&ty); - let obligation = cx.tcx.predicate_for_trait_def( - cx.param_env, - traits::ObligationCause::dummy(), - trait_id, - 0, - ty, - ty_params, - ); + let obligation = + cx.tcx + .predicate_for_trait_def(cx.param_env, traits::ObligationCause::dummy(), trait_id, 0, ty, ty_params); cx.tcx.infer_ctxt().enter(|infcx| { traits::SelectionContext::new(&infcx).evaluate_obligation_conservatively(&obligation) }) @@ -522,30 +516,27 @@ pub fn get_parent_expr<'c>(cx: &'c LateContext, e: &Expr) -> Option<&'c Expr> { if node_id == parent_id { return None; } - map.find(parent_id).and_then( - |node| if let Node::NodeExpr(parent) = - node - { + map.find(parent_id) + .and_then(|node| if let Node::NodeExpr(parent) = node { Some(parent) } else { None - }, - ) + }) } pub fn get_enclosing_block<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, node: NodeId) -> Option<&'tcx Block> { let map = &cx.tcx.hir; - let enclosing_node = map.get_enclosing_scope(node).and_then(|enclosing_id| { - map.find(enclosing_id) - }); + let enclosing_node = map.get_enclosing_scope(node) + .and_then(|enclosing_id| map.find(enclosing_id)); if let Some(node) = enclosing_node { match node { Node::NodeBlock(block) => Some(block), - Node::NodeItem(&Item { node: ItemFn(_, _, _, _, _, eid), .. }) => { - match cx.tcx.hir.body(eid).value.node { - ExprBlock(ref block) => Some(block), - _ => None, - } + Node::NodeItem(&Item { + node: ItemFn(_, _, _, _, _, eid), + .. + }) => match cx.tcx.hir.body(eid).value.node { + ExprBlock(ref block) => Some(block), + _ => None, }, _ => None, } @@ -704,9 +695,9 @@ impl LimitStack { Self { stack: vec![limit] } } pub fn limit(&self) -> u64 { - *self.stack.last().expect( - "there should always be a value in the stack", - ) + *self.stack + .last() + .expect("there should always be a value in the stack") } pub fn push_attrs(&mut self, sess: &Session, attrs: &[ast::Attribute], name: &'static str) { let stack = &mut self.stack; @@ -741,9 +732,10 @@ fn parse_attrs(sess: &Session, attrs: &[ast::Attribute], name: &' /// See also `is_direct_expn_of`. pub fn is_expn_of(mut span: Span, name: &str) -> Option { loop { - let span_name_span = span.ctxt().outer().expn_info().map(|ei| { - (ei.callee.name(), ei.call_site) - }); + let span_name_span = span.ctxt() + .outer() + .expn_info() + .map(|ei| (ei.callee.name(), ei.call_site)); match span_name_span { Some((mac_name, new_span)) if mac_name == name => return Some(new_span), @@ -763,9 +755,10 @@ pub fn is_expn_of(mut span: Span, name: &str) -> Option { /// `bar!` by /// `is_direct_expn_of`. pub fn is_direct_expn_of(span: Span, name: &str) -> Option { - let span_name_span = span.ctxt().outer().expn_info().map(|ei| { - (ei.callee.name(), ei.call_site) - }); + let span_name_span = span.ctxt() + .outer() + .expn_info() + .map(|ei| (ei.callee.name(), ei.call_site)); match span_name_span { Some((mac_name, new_span)) if mac_name == name => Some(new_span), @@ -800,7 +793,11 @@ pub fn camel_case_until(s: &str) -> usize { return i; } } - if up { last_i } else { s.len() } + if up { + last_i + } else { + s.len() + } } /// Return index of the last camel-case component of `s`. @@ -844,9 +841,9 @@ pub fn return_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, fn_item: NodeId) -> Ty<'t // <'b> Foo<'b>` but // not for type parameters. pub fn same_tys<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> bool { - cx.tcx.infer_ctxt().enter(|infcx| { - infcx.can_eq(cx.param_env, a, b).is_ok() - }) + cx.tcx + .infer_ctxt() + .enter(|infcx| infcx.can_eq(cx.param_env, a, b).is_ok()) } /// Return whether the given type is an `unsafe` function. @@ -875,36 +872,28 @@ pub fn is_refutable(cx: &LateContext, pat: &Pat) -> bool { } match pat.node { - PatKind::Binding(..) | - PatKind::Wild => false, - PatKind::Box(ref pat) | - PatKind::Ref(ref pat, _) => is_refutable(cx, pat), - PatKind::Lit(..) | - PatKind::Range(..) => true, + PatKind::Binding(..) | PatKind::Wild => false, + PatKind::Box(ref pat) | PatKind::Ref(ref pat, _) => is_refutable(cx, pat), + PatKind::Lit(..) | PatKind::Range(..) => true, PatKind::Path(ref qpath) => is_enum_variant(cx, qpath, pat.hir_id), PatKind::Tuple(ref pats, _) => are_refutable(cx, pats.iter().map(|pat| &**pat)), - PatKind::Struct(ref qpath, ref fields, _) => { - if is_enum_variant(cx, qpath, pat.hir_id) { - true - } else { - are_refutable(cx, fields.iter().map(|field| &*field.node.pat)) - } + PatKind::Struct(ref qpath, ref fields, _) => if is_enum_variant(cx, qpath, pat.hir_id) { + true + } else { + are_refutable(cx, fields.iter().map(|field| &*field.node.pat)) }, - PatKind::TupleStruct(ref qpath, ref pats, _) => { - if is_enum_variant(cx, qpath, pat.hir_id) { - true - } else { - are_refutable(cx, pats.iter().map(|pat| &**pat)) - } - }, - PatKind::Slice(ref head, ref middle, ref tail) => { - are_refutable( - cx, - head.iter().chain(middle).chain(tail.iter()).map( - |pat| &**pat, - ), - ) + PatKind::TupleStruct(ref qpath, ref pats, _) => if is_enum_variant(cx, qpath, pat.hir_id) { + true + } else { + are_refutable(cx, pats.iter().map(|pat| &**pat)) }, + PatKind::Slice(ref head, ref middle, ref tail) => are_refutable( + cx, + head.iter() + .chain(middle) + .chain(tail.iter()) + .map(|pat| &**pat), + ), } } @@ -1029,9 +1018,9 @@ pub fn is_try(expr: &Expr) -> Option<&Expr> { } pub fn type_size<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> Option { - ty.layout(cx.tcx, cx.param_env).ok().map(|layout| { - layout.size(cx.tcx).bytes() - }) + ty.layout(cx.tcx, cx.param_env) + .ok() + .map(|layout| layout.size(cx.tcx).bytes()) } /// Returns true if the lint is allowed in the current context diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index 4dc2314accb9..ec0a351b8b09 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -33,9 +33,7 @@ pub const ONE: Sugg<'static> = Sugg::NonParen(Cow::Borrowed("1")); impl<'a> Display for Sugg<'a> { fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { match *self { - Sugg::NonParen(ref s) | - Sugg::MaybeParen(ref s) | - Sugg::BinOp(_, ref s) => s.fmt(f), + Sugg::NonParen(ref s) | Sugg::MaybeParen(ref s) | Sugg::BinOp(_, ref s) => s.fmt(f), } } } @@ -178,12 +176,10 @@ impl<'a> Sugg<'a> { match self { Sugg::NonParen(..) => self, // (x) and (x).y() both don't need additional parens - Sugg::MaybeParen(sugg) => { - if sugg.starts_with('(') && sugg.ends_with(')') { - Sugg::MaybeParen(sugg) - } else { - Sugg::NonParen(format!("({})", sugg).into()) - } + Sugg::MaybeParen(sugg) => if sugg.starts_with('(') && sugg.ends_with(')') { + Sugg::MaybeParen(sugg) + } else { + Sugg::NonParen(format!("({})", sugg).into()) }, Sugg::BinOp(_, sugg) => Sugg::NonParen(format!("({})", sugg).into()), } @@ -273,8 +269,8 @@ pub fn make_assoc(op: AssocOp, lhs: &Sugg, rhs: &Sugg) -> Sugg<'static> { fn needs_paren(op: &AssocOp, other: &AssocOp, dir: Associativity) -> bool { other.precedence() < op.precedence() || (other.precedence() == op.precedence() && - ((op != other && associativity(op) != dir) || - (op == other && associativity(op) != Associativity::Both))) || + ((op != other && associativity(op) != dir) || + (op == other && associativity(op) != Associativity::Both))) || is_shift(op) && is_arith(other) || is_shift(other) && is_arith(op) } @@ -293,12 +289,24 @@ pub fn make_assoc(op: AssocOp, lhs: &Sugg, rhs: &Sugg) -> Sugg<'static> { let lhs = ParenHelper::new(lhs_paren, lhs); let rhs = ParenHelper::new(rhs_paren, rhs); let sugg = match op { - AssocOp::Add | AssocOp::BitAnd | AssocOp::BitOr | AssocOp::BitXor | AssocOp::Divide | AssocOp::Equal | - AssocOp::Greater | AssocOp::GreaterEqual | AssocOp::LAnd | AssocOp::LOr | AssocOp::Less | - AssocOp::LessEqual | AssocOp::Modulus | AssocOp::Multiply | AssocOp::NotEqual | AssocOp::ShiftLeft | - AssocOp::ShiftRight | AssocOp::Subtract => { - format!("{} {} {}", lhs, op.to_ast_binop().expect("Those are AST ops").to_string(), rhs) - }, + AssocOp::Add | + AssocOp::BitAnd | + AssocOp::BitOr | + AssocOp::BitXor | + AssocOp::Divide | + AssocOp::Equal | + AssocOp::Greater | + AssocOp::GreaterEqual | + AssocOp::LAnd | + AssocOp::LOr | + AssocOp::Less | + AssocOp::LessEqual | + AssocOp::Modulus | + AssocOp::Multiply | + AssocOp::NotEqual | + AssocOp::ShiftLeft | + AssocOp::ShiftRight | + AssocOp::Subtract => format!("{} {} {}", lhs, op.to_ast_binop().expect("Those are AST ops").to_string(), rhs), AssocOp::Inplace => format!("in ({}) {}", lhs, rhs), AssocOp::Assign => format!("{} = {}", lhs, rhs), AssocOp::AssignOp(op) => format!("{} {}= {}", lhs, token_to_string(&token::BinOp(op)), rhs), @@ -343,7 +351,16 @@ fn associativity(op: &AssocOp) -> Associativity { match *op { Inplace | Assign | AssignOp(_) => Associativity::Right, Add | BitAnd | BitOr | BitXor | LAnd | LOr | Multiply | As | Colon => Associativity::Both, - Divide | Equal | Greater | GreaterEqual | Less | LessEqual | Modulus | NotEqual | ShiftLeft | ShiftRight | + Divide | + Equal | + Greater | + GreaterEqual | + Less | + LessEqual | + Modulus | + NotEqual | + ShiftLeft | + ShiftRight | Subtract => Associativity::Left, DotDot | DotDotDot => Associativity::None, } @@ -393,9 +410,8 @@ fn astbinop2assignop(op: ast::BinOp) -> AssocOp { /// before it on its line. fn indentation<'a, T: LintContext<'a>>(cx: &T, span: Span) -> Option { let lo = cx.sess().codemap().lookup_char_pos(span.lo()); - if let Some(line) = lo.file.get_line( - lo.line - 1, /* line numbers in `Loc` are 1-based */ - ) + if let Some(line) = lo.file + .get_line(lo.line - 1 /* line numbers in `Loc` are 1-based */) { if let Some((pos, _)) = line.char_indices().find(|&(_, c)| c != ' ' && c != '\t') { // we can mix char and byte positions here because we only consider `[ \t]` diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index 95f3c913dac6..71f53a3e0519 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -72,14 +72,12 @@ fn check_vec_macro(cx: &LateContext, vec_args: &higher::VecArgs, span: Span) { return; } }, - higher::VecArgs::Vec(args) => { - if let Some(last) = args.iter().last() { - let span = args[0].span.to(last.span); + higher::VecArgs::Vec(args) => if let Some(last) = args.iter().last() { + let span = args[0].span.to(last.span); - format!("&[{}]", snippet(cx, span, "..")).into() - } else { - "&[]".into() - } + format!("&[{}]", snippet(cx, span, "..")).into() + } else { + "&[]".into() }, }; diff --git a/clippy_lints/src/zero_div_zero.rs b/clippy_lints/src/zero_div_zero.rs index 888cd3390965..5ff9fb9ffd5d 100644 --- a/clippy_lints/src/zero_div_zero.rs +++ b/clippy_lints/src/zero_div_zero.rs @@ -1,4 +1,4 @@ -use consts::{Constant, constant_simple, FloatWidth}; +use consts::{constant_simple, Constant, FloatWidth}; use rustc::lint::*; use rustc::hir::*; use utils::span_help_and_lint; diff --git a/mini-macro/src/lib.rs b/mini-macro/src/lib.rs index 4b0c5ea5afde..fda167b69c70 100644 --- a/mini-macro/src/lib.rs +++ b/mini-macro/src/lib.rs @@ -1,13 +1,12 @@ #![feature(plugin_registrar, rustc_private)] -extern crate syntax; -extern crate rustc; extern crate rustc_plugin; +extern crate syntax; use syntax::codemap::Span; use syntax::tokenstream::TokenTree; -use syntax::ext::base::{ExtCtxt, MacResult, MacEager}; -use syntax::ext::build::AstBuilder; // trait for expr_usize +use syntax::ext::base::{ExtCtxt, MacEager, MacResult}; +use syntax::ext::build::AstBuilder; // trait for expr_usize use rustc_plugin::Registry; fn expand_macro(cx: &mut ExtCtxt, sp: Span, _: &[TokenTree]) -> Box { diff --git a/src/main.rs b/src/main.rs index 054ceae94e3b..89de07115c54 100644 --- a/src/main.rs +++ b/src/main.rs @@ -45,13 +45,8 @@ impl<'a> CompilerCalls<'a> for ClippyCompilerCalls { descriptions: &rustc_errors::registry::Registry, output: ErrorOutputType, ) -> Compilation { - self.default.early_callback( - matches, - sopts, - cfg, - descriptions, - output, - ) + self.default + .early_callback(matches, sopts, cfg, descriptions, output) } fn no_input( &mut self, @@ -62,14 +57,8 @@ impl<'a> CompilerCalls<'a> for ClippyCompilerCalls { ofile: &Option, descriptions: &rustc_errors::registry::Registry, ) -> Option<(Input, Option)> { - self.default.no_input( - matches, - sopts, - cfg, - odir, - ofile, - descriptions, - ) + self.default + .no_input(matches, sopts, cfg, odir, ofile, descriptions) } fn late_callback( &mut self, @@ -79,13 +68,8 @@ impl<'a> CompilerCalls<'a> for ClippyCompilerCalls { odir: &Option, ofile: &Option, ) -> Compilation { - self.default.late_callback( - matches, - sess, - input, - odir, - ofile, - ) + self.default + .late_callback(matches, sess, input, odir, ofile) } fn build_controller(&mut self, sess: &Session, matches: &getopts::Matches) -> driver::CompileController<'a> { let mut control = self.default.build_controller(sess, matches); @@ -101,7 +85,7 @@ impl<'a> CompilerCalls<'a> for ClippyCompilerCalls { .as_ref() .expect( "at this compilation stage \ - the krate must be parsed", + the krate must be parsed", ) .span, ); @@ -203,13 +187,13 @@ pub fn main() { .skip(2) .find(|val| val.starts_with("--manifest-path=")); - let mut metadata = - if let Ok(metadata) = cargo_metadata::metadata(manifest_path_arg.as_ref().map(AsRef::as_ref)) { - metadata - } else { - let _ = io::stderr().write_fmt(format_args!("error: Could not obtain cargo metadata.\n")); - process::exit(101); - }; + let mut metadata = if let Ok(metadata) = cargo_metadata::metadata(manifest_path_arg.as_ref().map(AsRef::as_ref)) + { + metadata + } else { + let _ = io::stderr().write_fmt(format_args!("error: Could not obtain cargo metadata.\n")); + process::exit(101); + }; let manifest_path = manifest_path_arg.map(|arg| { Path::new(&arg["--manifest-path=".len()..]) @@ -359,7 +343,6 @@ fn process(old_args: I) -> Result<(), i32> where I: Iterator, { - let mut args = vec!["rustc".to_owned()]; let mut found_dashes = false; diff --git a/tests/compile-test.rs b/tests/compile-test.rs index a5d55978d096..8fa0d440ee7b 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -29,6 +29,8 @@ fn compile_test() { prepare_env(); run_mode("run-pass", "run-pass"); run_mode("ui", "ui"); - #[cfg(target_os = "windows")] run_mode("ui-windows", "ui"); - #[cfg(not(target_os = "windows"))] run_mode("ui-posix", "ui"); + #[cfg(target_os = "windows")] + run_mode("ui-windows", "ui"); + #[cfg(not(target_os = "windows"))] + run_mode("ui-posix", "ui"); } diff --git a/tests/dogfood.rs b/tests/dogfood.rs index 378d14972aa9..aa2c4d03bd57 100644 --- a/tests/dogfood.rs +++ b/tests/dogfood.rs @@ -5,7 +5,7 @@ extern crate compiletest_rs as compiletest; extern crate test; -use std::env::{var, set_var}; +use std::env::{set_var, var}; use std::path::PathBuf; use test::TestPaths; diff --git a/tests/issue-825.rs b/tests/issue-825.rs index 685715a111c3..50de10b936ca 100644 --- a/tests/issue-825.rs +++ b/tests/issue-825.rs @@ -1,14 +1,12 @@ #![feature(plugin)] #![plugin(clippy)] - #![allow(warnings)] // this should compile in a reasonable amount of time fn rust_type_id(name: &str) { - if "bool" == &name[..] || "uint" == &name[..] || "u8" == &name[..] || "u16" == &name[..] || - "u32" == &name[..] || "f32" == &name[..] || "f64" == &name[..] || "i8" == &name[..] || - "i16" == &name[..] || "i32" == &name[..] || - "i64" == &name[..] || "Self" == &name[..] || "str" == &name[..] + if "bool" == &name[..] || "uint" == &name[..] || "u8" == &name[..] || "u16" == &name[..] || "u32" == &name[..] || + "f32" == &name[..] || "f64" == &name[..] || "i8" == &name[..] || "i16" == &name[..] || + "i32" == &name[..] || "i64" == &name[..] || "Self" == &name[..] || "str" == &name[..] { unreachable!(); } diff --git a/tests/matches.rs b/tests/matches.rs index 2f9a61ed768b..42d1154bf1a7 100644 --- a/tests/matches.rs +++ b/tests/matches.rs @@ -21,13 +21,11 @@ fn test_overlapping() { assert_eq!(None, overlapping(&[sp(1, Bound::Included(4)), sp(5, Bound::Included(6))])); assert_eq!( None, - overlapping( - &[ - sp(1, Bound::Included(4)), - sp(5, Bound::Included(6)), - sp(10, Bound::Included(11)), - ], - ) + overlapping(&[ + sp(1, Bound::Included(4)), + sp(5, Bound::Included(6)), + sp(10, Bound::Included(11)) + ],) ); assert_eq!( Some((&sp(1, Bound::Included(4)), &sp(3, Bound::Included(6)))), @@ -35,12 +33,10 @@ fn test_overlapping() { ); assert_eq!( Some((&sp(5, Bound::Included(6)), &sp(6, Bound::Included(11)))), - overlapping( - &[ - sp(1, Bound::Included(4)), - sp(5, Bound::Included(6)), - sp(6, Bound::Included(11)), - ], - ) + overlapping(&[ + sp(1, Bound::Included(4)), + sp(5, Bound::Included(6)), + sp(6, Bound::Included(11)) + ],) ); } diff --git a/tests/needless_continue_helpers.rs b/tests/needless_continue_helpers.rs index a669b6f94776..853f64b46984 100644 --- a/tests/needless_continue_helpers.rs +++ b/tests/needless_continue_helpers.rs @@ -1,7 +1,8 @@ // Tests for the various helper functions used by the needless_continue // lint that don't belong in utils. + extern crate clippy_lints; -use clippy_lints::needless_continue::{erode_from_back, erode_block, erode_from_front}; +use clippy_lints::needless_continue::{erode_block, erode_from_back, erode_from_front}; #[test] #[cfg_attr(rustfmt, rustfmt_skip)] From b32631794a413cea7ce29abd9f194fff59f05fa1 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 5 Sep 2017 12:53:52 +0200 Subject: [PATCH 2/3] Rustfmt for_loop.rs and add false positive tests --- tests/ui/for_loop.rs | 287 ++++++++++++++++++------ tests/ui/for_loop.stderr | 463 ++++++++++++++++++++++----------------- 2 files changed, 483 insertions(+), 267 deletions(-) diff --git a/tests/ui/for_loop.rs b/tests/ui/for_loop.rs index 0dbebcdca2cf..b4aee6d8ce23 100644 --- a/tests/ui/for_loop.rs +++ b/tests/ui/for_loop.rs @@ -4,14 +4,14 @@ use std::collections::*; use std::rc::Rc; -static STATIC: [usize; 4] = [ 0, 1, 8, 16 ]; -const CONST: [usize; 4] = [ 0, 1, 8, 16 ]; +static STATIC: [usize; 4] = [0, 1, 8, 16]; +const CONST: [usize; 4] = [0, 1, 8, 16]; #[warn(clippy)] fn for_loop_over_option_and_result() { let option = Some(1); let result = option.ok_or("x not found"); - let v = vec![0,1,2]; + let v = vec![0, 1, 2]; // check FOR_LOOP_OVER_OPTION lint for x in option { @@ -27,7 +27,8 @@ fn for_loop_over_option_and_result() { println!("{}", x); } - // make sure LOOP_OVER_NEXT lint takes precedence when next() is the last call in the chain + // make sure LOOP_OVER_NEXT lint takes precedence when next() is the last call + // in the chain for x in v.iter().next() { println!("{}", x); } @@ -72,7 +73,8 @@ impl Unrelated { } } -#[warn(needless_range_loop, explicit_iter_loop, explicit_into_iter_loop, iter_next_loop, reverse_range_loop, explicit_counter_loop, for_kv_map)] +#[warn(needless_range_loop, explicit_iter_loop, explicit_into_iter_loop, iter_next_loop, reverse_range_loop, + explicit_counter_loop, for_kv_map)] #[warn(unused_collect)] #[allow(linkedlist, shadow_unrelated, unnecessary_mut_passed, cyclomatic_complexity, similar_names)] #[allow(many_single_char_names, unused_variables)] @@ -90,7 +92,9 @@ fn main() { println!("{}", vec[i]); // ok, not the `i` of the for-loop } - for i in 0..vec.len() { let _ = vec[i]; } + for i in 0..vec.len() { + let _ = vec[i]; + } // ICE #746 for j in 0..4 { @@ -104,7 +108,8 @@ fn main() { for i in 0..vec.len() { println!("{} {}", vec[i], i); } - for i in 0..vec.len() { // not an error, indexing more than one variable + for i in 0..vec.len() { + // not an error, indexing more than one variable println!("{} {}", vec[i], vec2[i]); } @@ -156,97 +161,104 @@ fn main() { println!("{}", i); } - for i in 5...5 { // not an error, this is the range with only one element “5” + for i in 5...5 { + // not an error, this is the range with only one element “5” println!("{}", i); } - for i in 0..10 { // not an error, the start index is less than the end index + for i in 0..10 { + // not an error, the start index is less than the end index println!("{}", i); } - for i in -10..0 { // not an error + for i in -10..0 { + // not an error println!("{}", i); } - for i in (10..0).map(|x| x * 2) { // not an error, it can't be known what arbitrary methods do to a range + for i in (10..0).map(|x| x * 2) { + // not an error, it can't be known what arbitrary methods do to a range println!("{}", i); } // testing that the empty range lint folds constants - for i in 10..5+4 { + for i in 10..5 + 4 { println!("{}", i); } - for i in (5+2)..(3-1) { + for i in (5 + 2)..(3 - 1) { println!("{}", i); } - for i in (5+2)..(8-1) { + for i in (5 + 2)..(8 - 1) { println!("{}", i); } - for i in (2*2)..(2*3) { // no error, 4..6 is fine + for i in (2 * 2)..(2 * 3) { + // no error, 4..6 is fine println!("{}", i); } let x = 42; - for i in x..10 { // no error, not constant-foldable + for i in x..10 { + // no error, not constant-foldable println!("{}", i); } // See #601 - for i in 0..10 { // no error, id_col does not exist outside the loop + for i in 0..10 { + // no error, id_col does not exist outside the loop let mut id_col = vec![0f64; 10]; id_col[i] = 1f64; } - for _v in vec.iter() { } + for _v in vec.iter() {} - for _v in vec.iter_mut() { } + for _v in vec.iter_mut() {} - let out_vec = vec![1,2,3]; - for _v in out_vec.into_iter() { } + let out_vec = vec![1, 2, 3]; + for _v in out_vec.into_iter() {} let array = [1, 2, 3]; for _v in array.into_iter() {} - for _v in &vec { } // these are fine - for _v in &mut vec { } // these are fine + for _v in &vec {} // these are fine + for _v in &mut vec {} // these are fine - for _v in [1, 2, 3].iter() { } + for _v in [1, 2, 3].iter() {} - for _v in (&mut [1, 2, 3]).iter() { } // no error + for _v in (&mut [1, 2, 3]).iter() {} // no error for _v in [0; 32].iter() {} for _v in [0; 33].iter() {} // no error let ll: LinkedList<()> = LinkedList::new(); - for _v in ll.iter() { } + for _v in ll.iter() {} let vd: VecDeque<()> = VecDeque::new(); - for _v in vd.iter() { } + for _v in vd.iter() {} let bh: BinaryHeap<()> = BinaryHeap::new(); - for _v in bh.iter() { } + for _v in bh.iter() {} let hm: HashMap<(), ()> = HashMap::new(); - for _v in hm.iter() { } + for _v in hm.iter() {} let bt: BTreeMap<(), ()> = BTreeMap::new(); - for _v in bt.iter() { } + for _v in bt.iter() {} let hs: HashSet<()> = HashSet::new(); - for _v in hs.iter() { } + for _v in hs.iter() {} let bs: BTreeSet<()> = BTreeSet::new(); - for _v in bs.iter() { } + for _v in bs.iter() {} - for _v in vec.iter().next() { } + for _v in vec.iter().next() {} let u = Unrelated(vec![]); - for _v in u.next() { } // no error - for _v in u.iter() { } // no error + for _v in u.next() {} // no error + for _v in u.iter() {} // no error let mut out = vec![]; vec.iter().cloned().map(|x| out.push(x)).collect::>(); @@ -254,82 +266,135 @@ fn main() { // Loop with explicit counter variable let mut _index = 0; - for _v in &vec { _index += 1 } + for _v in &vec { + _index += 1 + } let mut _index = 1; _index = 0; - for _v in &vec { _index += 1 } + for _v in &vec { + _index += 1 + } // Potential false positives let mut _index = 0; _index = 1; - for _v in &vec { _index += 1 } + for _v in &vec { + _index += 1 + } let mut _index = 0; _index += 1; - for _v in &vec { _index += 1 } + for _v in &vec { + _index += 1 + } let mut _index = 0; - if true { _index = 1 } - for _v in &vec { _index += 1 } + if true { + _index = 1 + } + for _v in &vec { + _index += 1 + } let mut _index = 0; let mut _index = 1; - for _v in &vec { _index += 1 } + for _v in &vec { + _index += 1 + } let mut _index = 0; - for _v in &vec { _index += 1; _index += 1 } + for _v in &vec { + _index += 1; + _index += 1 + } let mut _index = 0; - for _v in &vec { _index *= 2; _index += 1 } + for _v in &vec { + _index *= 2; + _index += 1 + } let mut _index = 0; - for _v in &vec { _index = 1; _index += 1 } + for _v in &vec { + _index = 1; + _index += 1 + } let mut _index = 0; - for _v in &vec { let mut _index = 0; _index += 1 } + for _v in &vec { + let mut _index = 0; + _index += 1 + } let mut _index = 0; - for _v in &vec { _index += 1; _index = 0; } + for _v in &vec { + _index += 1; + _index = 0; + } let mut _index = 0; - for _v in &vec { for _x in 0..1 { _index += 1; }; _index += 1 } + for _v in &vec { + for _x in 0..1 { + _index += 1; + } + _index += 1 + } let mut _index = 0; - for x in &vec { if *x == 1 { _index += 1 } } + for x in &vec { + if *x == 1 { + _index += 1 + } + } let mut _index = 0; - if true { _index = 1 }; - for _v in &vec { _index += 1 } + if true { + _index = 1 + }; + for _v in &vec { + _index += 1 + } let mut _index = 1; - if false { _index = 0 }; - for _v in &vec { _index += 1 } + if false { + _index = 0 + }; + for _v in &vec { + _index += 1 + } let mut index = 0; - { let mut _x = &mut index; } - for _v in &vec { _index += 1 } + { + let mut _x = &mut index; + } + for _v in &vec { + _index += 1 + } let mut index = 0; - for _v in &vec { index += 1 } + for _v in &vec { + index += 1 + } println!("index: {}", index); for_loop_over_option_and_result(); - let m : HashMap = HashMap::new(); + let m: HashMap = HashMap::new(); for (_, v) in &m { let _v = v; } - let m : Rc> = Rc::new(HashMap::new()); + let m: Rc> = Rc::new(HashMap::new()); for (_, v) in &*m { let _v = v; - // Here the `*` is not actually necesarry, but the test tests that we don't suggest + // Here the `*` is not actually necesarry, but the test tests that we don't + // suggest // `in *m.values()` as we used to } - let mut m : HashMap = HashMap::new(); + let mut m: HashMap = HashMap::new(); for (_, v) in &mut m { let _v = v; } @@ -339,7 +404,7 @@ fn main() { let _v = v; } - let m : HashMap = HashMap::new(); + let m: HashMap = HashMap::new(); let rm = &m; for (k, _value) in rm { let _k = k; @@ -347,8 +412,12 @@ fn main() { test_for_kv_map(); - fn f(_: &T, _: &T) -> bool { unimplemented!() } - fn g(_: &mut [T], _: usize, _: usize) { unimplemented!() } + fn f(_: &T, _: &T) -> bool { + unimplemented!() + } + fn g(_: &mut [T], _: usize, _: usize) { + unimplemented!() + } for i in 1..vec.len() { if f(&vec[i - 1], &vec[i]) { g(&mut vec, i - 1, i); @@ -362,7 +431,7 @@ fn main() { #[allow(used_underscore_binding)] fn test_for_kv_map() { - let m : HashMap = HashMap::new(); + let m: HashMap = HashMap::new(); // No error, _value is actually used for (k, _value) in &m { @@ -372,7 +441,7 @@ fn test_for_kv_map() { } #[allow(dead_code)] -fn partition(v: &mut [T]) -> usize { +fn partition(v: &mut [T]) -> usize { let pivot = v.len() - 1; let mut i = 0; for j in 0..pivot { @@ -384,3 +453,91 @@ fn partition(v: &mut [T]) -> usize { v.swap(i, pivot); i } + +const LOOP_OFFSET: usize = 5000; + +#[warn(needless_range_loop)] +pub fn manual_copy(src: &[i32], dst: &mut [i32], dst2: &mut [i32]) { + // plain manual memcpy + for i in 0..src.len() { + dst[i] = src[i]; + } + + // dst offset memcpy + for i in 0..src.len() { + dst[i + 10] = src[i]; + } + + // src offset memcpy + for i in 0..src.len() { + dst[i] = src[i + 10]; + } + + // src offset memcpy + for i in 11..src.len() { + dst[i] = src[i - 10]; + } + + // overwrite entire dst + for i in 0..dst.len() { + dst[i] = src[i]; + } + + // manual copy with branch - can't easily convert to memcpy! + for i in 0..src.len() { + dst[i] = src[i]; + if dst[i] > 5 { + break; + } + } + + // multiple copies - suggest two memcpy statements + for i in 10..256 { + dst[i] = src[i - 5]; + dst2[i + 500] = src[i] + } + + // this is a reversal - the copy lint shouldn't be triggered + for i in 10..LOOP_OFFSET { + dst[i + LOOP_OFFSET] = src[LOOP_OFFSET - i]; + } + + let some_var = 5; + // Offset in variable + for i in 10..LOOP_OFFSET { + dst[i + LOOP_OFFSET] = src[i - some_var]; + } + + // Non continuous copy - don't trigger lint + for i in 0..10 { + dst[i + i] = src[i]; + } + + let src_vec = vec![1, 2, 3, 4, 5]; + let mut dst_vec = vec![0, 0, 0, 0, 0]; + + // make sure vectors are supported + for i in 0..src_vec.len() { + dst_vec[i] = src_vec[i]; + } + + // lint should not trigger when either + // source or destination type is not + // slice-like, like DummyStruct + struct DummyStruct(i32); + + impl ::std::ops::Index for DummyStruct { + type Output = i32; + + fn index(&self, _: usize) -> &i32 { + &self.0 + } + } + + let src = DummyStruct(5); + let mut dst_vec = vec![0; 10]; + + for i in 0..10 { + dst_vec[i] = src[i]; + } +} diff --git a/tests/ui/for_loop.stderr b/tests/ui/for_loop.stderr index d4954357665e..090caf1779a5 100644 --- a/tests/ui/for_loop.stderr +++ b/tests/ui/for_loop.stderr @@ -25,478 +25,537 @@ error: for loop over `option.ok_or("x not found")`, which is a `Result`. This is = help: consider replacing `for x in option.ok_or("x not found")` with `if let Ok(x) = option.ok_or("x not found")` error: you are iterating over `Iterator::next()` which is an Option; this will compile but is probably not what you want - --> $DIR/for_loop.rs:31:5 + --> $DIR/for_loop.rs:32:5 | -31 | / for x in v.iter().next() { -32 | | println!("{}", x); -33 | | } +32 | / for x in v.iter().next() { +33 | | println!("{}", x); +34 | | } | |_____^ | = note: `-D iter-next-loop` implied by `-D warnings` error: for loop over `v.iter().next().and(Some(0))`, which is an `Option`. This is more readably written as an `if let` statement. - --> $DIR/for_loop.rs:36:14 + --> $DIR/for_loop.rs:37:14 | -36 | for x in v.iter().next().and(Some(0)) { +37 | for x in v.iter().next().and(Some(0)) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider replacing `for x in v.iter().next().and(Some(0))` with `if let Some(x) = v.iter().next().and(Some(0))` error: for loop over `v.iter().next().ok_or("x not found")`, which is a `Result`. This is more readably written as an `if let` statement. - --> $DIR/for_loop.rs:40:14 + --> $DIR/for_loop.rs:41:14 | -40 | for x in v.iter().next().ok_or("x not found") { +41 | for x in v.iter().next().ok_or("x not found") { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider replacing `for x in v.iter().next().ok_or("x not found")` with `if let Ok(x) = v.iter().next().ok_or("x not found")` error: this loop never actually loops - --> $DIR/for_loop.rs:52:5 + --> $DIR/for_loop.rs:53:5 | -52 | / while let Some(x) = option { -53 | | println!("{}", x); -54 | | break; -55 | | } +53 | / while let Some(x) = option { +54 | | println!("{}", x); +55 | | break; +56 | | } | |_____^ | = note: `-D never-loop` implied by `-D warnings` error: this loop never actually loops - --> $DIR/for_loop.rs:58:5 + --> $DIR/for_loop.rs:59:5 | -58 | / while let Ok(x) = result { -59 | | println!("{}", x); -60 | | break; -61 | | } +59 | / while let Ok(x) = result { +60 | | println!("{}", x); +61 | | break; +62 | | } | |_____^ error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:84:5 + --> $DIR/for_loop.rs:86:5 | -84 | / for i in 0..vec.len() { -85 | | println!("{}", vec[i]); -86 | | } +86 | / for i in 0..vec.len() { +87 | | println!("{}", vec[i]); +88 | | } | |_____^ | = note: `-D needless-range-loop` implied by `-D warnings` help: consider using an iterator | -84 | for in &vec { +86 | for in &vec { | ^^^^^^ error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:93:5 + --> $DIR/for_loop.rs:95:5 | -93 | for i in 0..vec.len() { let _ = vec[i]; } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: consider using an iterator - | -93 | for in &vec { let _ = vec[i]; } - | ^^^^^^ - -error: the loop variable `j` is only used to index `STATIC`. - --> $DIR/for_loop.rs:96:5 - | -96 | / for j in 0..4 { -97 | | println!("{:?}", STATIC[j]); -98 | | } +95 | / for i in 0..vec.len() { +96 | | let _ = vec[i]; +97 | | } | |_____^ | help: consider using an iterator | -96 | for in STATIC.iter().take(4) { +95 | for in &vec { | ^^^^^^ -error: the loop variable `j` is only used to index `CONST`. +error: the loop variable `j` is only used to index `STATIC`. --> $DIR/for_loop.rs:100:5 | 100 | / for j in 0..4 { -101 | | println!("{:?}", CONST[j]); +101 | | println!("{:?}", STATIC[j]); 102 | | } | |_____^ | help: consider using an iterator | -100 | for in CONST.iter().take(4) { +100 | for in STATIC.iter().take(4) { | ^^^^^^ -error: the loop variable `i` is used to index `vec` +error: the loop variable `j` is only used to index `CONST`. --> $DIR/for_loop.rs:104:5 | -104 | / for i in 0..vec.len() { -105 | | println!("{} {}", vec[i], i); +104 | / for j in 0..4 { +105 | | println!("{:?}", CONST[j]); 106 | | } | |_____^ | help: consider using an iterator | -104 | for (i, ) in vec.iter().enumerate() { +104 | for in CONST.iter().take(4) { + | ^^^^^^ + +error: the loop variable `i` is used to index `vec` + --> $DIR/for_loop.rs:108:5 + | +108 | / for i in 0..vec.len() { +109 | | println!("{} {}", vec[i], i); +110 | | } + | |_____^ + | +help: consider using an iterator + | +108 | for (i, ) in vec.iter().enumerate() { | ^^^^^^^^^^^ error: the loop variable `i` is only used to index `vec2`. - --> $DIR/for_loop.rs:111:5 + --> $DIR/for_loop.rs:116:5 | -111 | / for i in 0..vec.len() { -112 | | println!("{}", vec2[i]); -113 | | } +116 | / for i in 0..vec.len() { +117 | | println!("{}", vec2[i]); +118 | | } | |_____^ | help: consider using an iterator | -111 | for in vec2.iter().take(vec.len()) { +116 | for in vec2.iter().take(vec.len()) { | ^^^^^^ error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:115:5 + --> $DIR/for_loop.rs:120:5 | -115 | / for i in 5..vec.len() { -116 | | println!("{}", vec[i]); -117 | | } +120 | / for i in 5..vec.len() { +121 | | println!("{}", vec[i]); +122 | | } | |_____^ | help: consider using an iterator | -115 | for in vec.iter().skip(5) { +120 | for in vec.iter().skip(5) { | ^^^^^^ error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:119:5 + --> $DIR/for_loop.rs:124:5 | -119 | / for i in 0..MAX_LEN { -120 | | println!("{}", vec[i]); -121 | | } +124 | / for i in 0..MAX_LEN { +125 | | println!("{}", vec[i]); +126 | | } | |_____^ | help: consider using an iterator | -119 | for in vec.iter().take(MAX_LEN) { +124 | for in vec.iter().take(MAX_LEN) { | ^^^^^^ error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:123:5 + --> $DIR/for_loop.rs:128:5 | -123 | / for i in 0...MAX_LEN { -124 | | println!("{}", vec[i]); -125 | | } +128 | / for i in 0...MAX_LEN { +129 | | println!("{}", vec[i]); +130 | | } | |_____^ | help: consider using an iterator | -123 | for in vec.iter().take(MAX_LEN + 1) { +128 | for in vec.iter().take(MAX_LEN + 1) { | ^^^^^^ error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:127:5 + --> $DIR/for_loop.rs:132:5 | -127 | / for i in 5..10 { -128 | | println!("{}", vec[i]); -129 | | } +132 | / for i in 5..10 { +133 | | println!("{}", vec[i]); +134 | | } | |_____^ | help: consider using an iterator | -127 | for in vec.iter().take(10).skip(5) { +132 | for in vec.iter().take(10).skip(5) { | ^^^^^^ error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:131:5 + --> $DIR/for_loop.rs:136:5 | -131 | / for i in 5...10 { -132 | | println!("{}", vec[i]); -133 | | } +136 | / for i in 5...10 { +137 | | println!("{}", vec[i]); +138 | | } | |_____^ | help: consider using an iterator | -131 | for in vec.iter().take(10 + 1).skip(5) { +136 | for in vec.iter().take(10 + 1).skip(5) { | ^^^^^^ error: the loop variable `i` is used to index `vec` - --> $DIR/for_loop.rs:135:5 + --> $DIR/for_loop.rs:140:5 | -135 | / for i in 5..vec.len() { -136 | | println!("{} {}", vec[i], i); -137 | | } +140 | / for i in 5..vec.len() { +141 | | println!("{} {}", vec[i], i); +142 | | } | |_____^ | help: consider using an iterator | -135 | for (i, ) in vec.iter().enumerate().skip(5) { +140 | for (i, ) in vec.iter().enumerate().skip(5) { | ^^^^^^^^^^^ error: the loop variable `i` is used to index `vec` - --> $DIR/for_loop.rs:139:5 + --> $DIR/for_loop.rs:144:5 | -139 | / for i in 5..10 { -140 | | println!("{} {}", vec[i], i); -141 | | } +144 | / for i in 5..10 { +145 | | println!("{} {}", vec[i], i); +146 | | } | |_____^ | help: consider using an iterator | -139 | for (i, ) in vec.iter().enumerate().take(10).skip(5) { +144 | for (i, ) in vec.iter().enumerate().take(10).skip(5) { | ^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:143:5 + --> $DIR/for_loop.rs:148:5 | -143 | / for i in 10..0 { -144 | | println!("{}", i); -145 | | } +148 | / for i in 10..0 { +149 | | println!("{}", i); +150 | | } | |_____^ | = note: `-D reverse-range-loop` implied by `-D warnings` help: consider using the following if you are attempting to iterate over this range in reverse | -143 | for i in (0..10).rev() { +148 | for i in (0..10).rev() { | ^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:147:5 + --> $DIR/for_loop.rs:152:5 | -147 | / for i in 10...0 { -148 | | println!("{}", i); -149 | | } +152 | / for i in 10...0 { +153 | | println!("{}", i); +154 | | } | |_____^ | help: consider using the following if you are attempting to iterate over this range in reverse | -147 | for i in (0...10).rev() { +152 | for i in (0...10).rev() { | ^^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:151:5 + --> $DIR/for_loop.rs:156:5 | -151 | / for i in MAX_LEN..0 { -152 | | println!("{}", i); -153 | | } +156 | / for i in MAX_LEN..0 { +157 | | println!("{}", i); +158 | | } | |_____^ | help: consider using the following if you are attempting to iterate over this range in reverse | -151 | for i in (0..MAX_LEN).rev() { +156 | for i in (0..MAX_LEN).rev() { | ^^^^^^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:155:5 + --> $DIR/for_loop.rs:160:5 | -155 | / for i in 5..5 { -156 | | println!("{}", i); -157 | | } +160 | / for i in 5..5 { +161 | | println!("{}", i); +162 | | } | |_____^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:176:5 + --> $DIR/for_loop.rs:185:5 | -176 | / for i in 10..5+4 { -177 | | println!("{}", i); -178 | | } +185 | / for i in 10..5 + 4 { +186 | | println!("{}", i); +187 | | } | |_____^ | help: consider using the following if you are attempting to iterate over this range in reverse | -176 | for i in (5+4..10).rev() { - | ^^^^^^^^^^^^^^^ +185 | for i in (5 + 4..10).rev() { + | ^^^^^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:180:5 + --> $DIR/for_loop.rs:189:5 | -180 | / for i in (5+2)..(3-1) { -181 | | println!("{}", i); -182 | | } +189 | / for i in (5 + 2)..(3 - 1) { +190 | | println!("{}", i); +191 | | } | |_____^ | help: consider using the following if you are attempting to iterate over this range in reverse | -180 | for i in ((3-1)..(5+2)).rev() { - | ^^^^^^^^^^^^^^^^^^^^ +189 | for i in ((3 - 1)..(5 + 2)).rev() { + | ^^^^^^^^^^^^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:184:5 + --> $DIR/for_loop.rs:193:5 | -184 | / for i in (5+2)..(8-1) { -185 | | println!("{}", i); -186 | | } +193 | / for i in (5 + 2)..(8 - 1) { +194 | | println!("{}", i); +195 | | } | |_____^ error: it is more idiomatic to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:203:15 + --> $DIR/for_loop.rs:215:15 | -203 | for _v in vec.iter() { } +215 | for _v in vec.iter() {} | ^^^^^^^^^^ help: to write this more concisely, try: `&vec` | = note: `-D explicit-iter-loop` implied by `-D warnings` error: it is more idiomatic to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:205:15 + --> $DIR/for_loop.rs:217:15 | -205 | for _v in vec.iter_mut() { } +217 | for _v in vec.iter_mut() {} | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut vec` error: it is more idiomatic to loop over containers instead of using explicit iteration methods` - --> $DIR/for_loop.rs:208:15 + --> $DIR/for_loop.rs:220:15 | -208 | for _v in out_vec.into_iter() { } +220 | for _v in out_vec.into_iter() {} | ^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `out_vec` | = note: `-D explicit-into-iter-loop` implied by `-D warnings` error: it is more idiomatic to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:211:15 + --> $DIR/for_loop.rs:223:15 | -211 | for _v in array.into_iter() {} +223 | for _v in array.into_iter() {} | ^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&array` -error: it is more idiomatic to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:216:15 - | -216 | for _v in [1, 2, 3].iter() { } - | ^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[1, 2, 3]` - -error: it is more idiomatic to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:220:15 - | -220 | for _v in [0; 32].iter() {} - | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[0; 32]` - -error: it is more idiomatic to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:225:15 - | -225 | for _v in ll.iter() { } - | ^^^^^^^^^ help: to write this more concisely, try: `&ll` - error: it is more idiomatic to loop over references to containers instead of using explicit iteration methods --> $DIR/for_loop.rs:228:15 | -228 | for _v in vd.iter() { } - | ^^^^^^^^^ help: to write this more concisely, try: `&vd` +228 | for _v in [1, 2, 3].iter() {} + | ^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[1, 2, 3]` error: it is more idiomatic to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:231:15 + --> $DIR/for_loop.rs:232:15 | -231 | for _v in bh.iter() { } - | ^^^^^^^^^ help: to write this more concisely, try: `&bh` - -error: it is more idiomatic to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:234:15 - | -234 | for _v in hm.iter() { } - | ^^^^^^^^^ help: to write this more concisely, try: `&hm` +232 | for _v in [0; 32].iter() {} + | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[0; 32]` error: it is more idiomatic to loop over references to containers instead of using explicit iteration methods --> $DIR/for_loop.rs:237:15 | -237 | for _v in bt.iter() { } - | ^^^^^^^^^ help: to write this more concisely, try: `&bt` +237 | for _v in ll.iter() {} + | ^^^^^^^^^ help: to write this more concisely, try: `&ll` error: it is more idiomatic to loop over references to containers instead of using explicit iteration methods --> $DIR/for_loop.rs:240:15 | -240 | for _v in hs.iter() { } - | ^^^^^^^^^ help: to write this more concisely, try: `&hs` +240 | for _v in vd.iter() {} + | ^^^^^^^^^ help: to write this more concisely, try: `&vd` error: it is more idiomatic to loop over references to containers instead of using explicit iteration methods --> $DIR/for_loop.rs:243:15 | -243 | for _v in bs.iter() { } +243 | for _v in bh.iter() {} + | ^^^^^^^^^ help: to write this more concisely, try: `&bh` + +error: it is more idiomatic to loop over references to containers instead of using explicit iteration methods + --> $DIR/for_loop.rs:246:15 + | +246 | for _v in hm.iter() {} + | ^^^^^^^^^ help: to write this more concisely, try: `&hm` + +error: it is more idiomatic to loop over references to containers instead of using explicit iteration methods + --> $DIR/for_loop.rs:249:15 + | +249 | for _v in bt.iter() {} + | ^^^^^^^^^ help: to write this more concisely, try: `&bt` + +error: it is more idiomatic to loop over references to containers instead of using explicit iteration methods + --> $DIR/for_loop.rs:252:15 + | +252 | for _v in hs.iter() {} + | ^^^^^^^^^ help: to write this more concisely, try: `&hs` + +error: it is more idiomatic to loop over references to containers instead of using explicit iteration methods + --> $DIR/for_loop.rs:255:15 + | +255 | for _v in bs.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&bs` error: you are iterating over `Iterator::next()` which is an Option; this will compile but is probably not what you want - --> $DIR/for_loop.rs:245:5 + --> $DIR/for_loop.rs:257:5 | -245 | for _v in vec.iter().next() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +257 | for _v in vec.iter().next() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: you are collect()ing an iterator and throwing away the result. Consider using an explicit for loop to exhaust the iterator - --> $DIR/for_loop.rs:252:5 + --> $DIR/for_loop.rs:264:5 | -252 | vec.iter().cloned().map(|x| out.push(x)).collect::>(); +264 | vec.iter().cloned().map(|x| out.push(x)).collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D unused-collect` implied by `-D warnings` error: the variable `_index` is used as a loop counter. Consider using `for (_index, item) in &vec.enumerate()` or similar iterators - --> $DIR/for_loop.rs:257:5 + --> $DIR/for_loop.rs:269:5 | -257 | for _v in &vec { _index += 1 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +269 | / for _v in &vec { +270 | | _index += 1 +271 | | } + | |_____^ | = note: `-D explicit-counter-loop` implied by `-D warnings` error: the variable `_index` is used as a loop counter. Consider using `for (_index, item) in &vec.enumerate()` or similar iterators - --> $DIR/for_loop.rs:261:5 + --> $DIR/for_loop.rs:275:5 | -261 | for _v in &vec { _index += 1 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +275 | / for _v in &vec { +276 | | _index += 1 +277 | | } + | |_____^ error: you seem to want to iterate on a map's values - --> $DIR/for_loop.rs:321:5 + --> $DIR/for_loop.rs:385:5 | -321 | / for (_, v) in &m { -322 | | let _v = v; -323 | | } +385 | / for (_, v) in &m { +386 | | let _v = v; +387 | | } | |_____^ | = note: `-D for-kv-map` implied by `-D warnings` help: use the corresponding method | -321 | for v in m.values() { +385 | for v in m.values() { | ^ error: you seem to want to iterate on a map's values - --> $DIR/for_loop.rs:326:5 + --> $DIR/for_loop.rs:390:5 | -326 | / for (_, v) in &*m { -327 | | let _v = v; -328 | | // Here the `*` is not actually necesarry, but the test tests that we don't suggest -329 | | // `in *m.values()` as we used to -330 | | } +390 | / for (_, v) in &*m { +391 | | let _v = v; +392 | | // Here the `*` is not actually necesarry, but the test tests that we don't +393 | | // suggest +394 | | // `in *m.values()` as we used to +395 | | } | |_____^ | help: use the corresponding method | -326 | for v in (*m).values() { +390 | for v in (*m).values() { | ^ error: you seem to want to iterate on a map's values - --> $DIR/for_loop.rs:333:5 + --> $DIR/for_loop.rs:398:5 | -333 | / for (_, v) in &mut m { -334 | | let _v = v; -335 | | } +398 | / for (_, v) in &mut m { +399 | | let _v = v; +400 | | } | |_____^ | help: use the corresponding method | -333 | for v in m.values_mut() { +398 | for v in m.values_mut() { | ^ error: you seem to want to iterate on a map's values - --> $DIR/for_loop.rs:338:5 + --> $DIR/for_loop.rs:403:5 | -338 | / for (_, v) in &mut *m { -339 | | let _v = v; -340 | | } +403 | / for (_, v) in &mut *m { +404 | | let _v = v; +405 | | } | |_____^ | help: use the corresponding method | -338 | for v in (*m).values_mut() { +403 | for v in (*m).values_mut() { | ^ error: you seem to want to iterate on a map's keys - --> $DIR/for_loop.rs:344:5 + --> $DIR/for_loop.rs:409:5 | -344 | / for (k, _value) in rm { -345 | | let _k = k; -346 | | } +409 | / for (k, _value) in rm { +410 | | let _k = k; +411 | | } | |_____^ | help: use the corresponding method | -344 | for k in rm.keys() { +409 | for k in rm.keys() { | ^ -error: aborting due to 50 previous errors +error: the loop variable `i` is used to index `src` + --> $DIR/for_loop.rs:467:5 + | +467 | / for i in 0..src.len() { +468 | | dst[i + 10] = src[i]; +469 | | } + | |_____^ + | +help: consider using an iterator + | +467 | for (i, ) in src.iter().enumerate() { + | ^^^^^^^^^^^ + +error: the loop variable `i` is used to index `dst` + --> $DIR/for_loop.rs:472:5 + | +472 | / for i in 0..src.len() { +473 | | dst[i] = src[i + 10]; +474 | | } + | |_____^ + | +help: consider using an iterator + | +472 | for (i, ) in dst.iter().enumerate().take(src.len()) { + | ^^^^^^^^^^^ + +error: the loop variable `i` is used to index `dst` + --> $DIR/for_loop.rs:477:5 + | +477 | / for i in 11..src.len() { +478 | | dst[i] = src[i - 10]; +479 | | } + | |_____^ + | +help: consider using an iterator + | +477 | for (i, ) in dst.iter().enumerate().take(src.len()).skip(11) { + | ^^^^^^^^^^^ + +error: the loop variable `i` is used to index `src` + --> $DIR/for_loop.rs:512:5 + | +512 | / for i in 0..10 { +513 | | dst[i + i] = src[i]; +514 | | } + | |_____^ + | +help: consider using an iterator + | +512 | for (i, ) in src.iter().enumerate().take(10) { + | ^^^^^^^^^^^ + +error: aborting due to 54 previous errors From 90f345df94ffa92760ce338208a034d0a3785a2d Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Mon, 4 Sep 2017 20:16:34 -0400 Subject: [PATCH 3/3] Add lint to detect manual slice copies --- clippy_lints/src/loops.rs | 344 +++++++++++++++++++++++++++++++++++--- tests/ui/for_loop.stderr | 81 +++++---- 2 files changed, 368 insertions(+), 57 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 2f87fe0f3963..6cf2b1d9fedc 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1,3 +1,4 @@ +use itertools::Itertools; use reexport::*; use rustc::hir::*; use rustc::hir::def::Def; @@ -15,10 +16,29 @@ use syntax::ast; use utils::sugg; use utils::{get_enclosing_block, get_parent_expr, higher, in_external_macro, is_integer_literal, is_refutable, - last_path_segment, match_trait_method, match_type, multispan_sugg, snippet, span_help_and_lint, span_lint, - span_lint_and_sugg, span_lint_and_then}; + last_path_segment, match_trait_method, match_type, multispan_sugg, snippet, snippet_opt, + span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then}; use utils::paths; +/// **What it does:** Checks for for loops that manually copy items between +/// slices that could be optimized by having a memcpy. +/// +/// **Why is this bad?** It is not as fast as a memcpy. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// for i in 0..src.len() { +/// dst[i + 64] = src[i]; +/// } +/// ``` +declare_lint! { + pub MANUAL_MEMCPY, + Warn, + "manually copying items between slices" +} + /// **What it does:** Checks for looping over the range of `0..len` of some /// collection just to get the values by index. /// @@ -314,6 +334,7 @@ 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, @@ -570,6 +591,249 @@ fn check_for_loop<'a, 'tcx>( check_for_loop_arg(cx, pat, arg, expr); check_for_loop_explicit_counter(cx, arg, body, expr); check_for_loop_over_map_kv(cx, pat, arg, body, expr); + detect_manual_memcpy(cx, pat, arg, body, expr); +} + +fn same_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr, var: DefId) -> bool { + if_let_chain! {[ + let ExprPath(ref qpath) = expr.node, + let QPath::Resolved(None, ref path) = *qpath, + path.segments.len() == 1, + // our variable! + cx.tables.qpath_def(qpath, expr.hir_id).def_id() == var + ], { + return true; + }} + + false +} + +struct Offset { + value: String, + negate: bool, +} + +impl Offset { + fn negative(s: String) -> Self { + Self { + value: s, + negate: true, + } + } + + fn positive(s: String) -> Self { + Self { + value: s, + negate: false, + } + } +} + +struct FixedOffsetVar { + var_name: String, + offset: Offset, +} + +fn is_slice_like<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty) -> bool { + let is_slice = match ty.sty { + ty::TyRef(_, ref subty) => is_slice_like(cx, subty.ty), + ty::TySlice(..) | ty::TyArray(..) => true, + _ => false, + }; + + is_slice || match_type(cx, ty, &paths::VEC) || match_type(cx, ty, &paths::VEC_DEQUE) +} + +fn get_fixed_offset_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr, var: DefId) -> Option { + fn extract_offset<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, e: &Expr, var: DefId) -> Option { + match e.node { + ExprLit(ref l) => match l.node { + ast::LitKind::Int(x, _ty) => Some(x.to_string()), + _ => None, + }, + ExprPath(..) if !same_var(cx, e, var) => Some(snippet_opt(cx, e.span).unwrap_or_else(|| "??".into())), + _ => None, + } + } + + if let ExprIndex(ref seqexpr, ref idx) = expr.node { + let ty = cx.tables.expr_ty(seqexpr); + if !is_slice_like(cx, ty) { + return None; + } + + let offset = match idx.node { + ExprBinary(op, ref lhs, ref rhs) => match op.node { + BinOp_::BiAdd => { + let offset_opt = if same_var(cx, lhs, var) { + extract_offset(cx, rhs, var) + } else if same_var(cx, rhs, var) { + extract_offset(cx, lhs, var) + } else { + None + }; + + offset_opt.map(Offset::positive) + }, + BinOp_::BiSub if same_var(cx, lhs, var) => extract_offset(cx, rhs, var).map(Offset::negative), + _ => None, + }, + ExprPath(..) => if same_var(cx, idx, var) { + Some(Offset::positive("0".into())) + } else { + None + }, + _ => None, + }; + + offset.map(|o| { + FixedOffsetVar { + var_name: snippet_opt(cx, seqexpr.span).unwrap_or_else(|| "???".into()), + offset: o, + } + }) + } else { + None + } +} + +fn get_indexed_assignments<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + body: &Expr, + var: DefId, +) -> Vec<(FixedOffsetVar, FixedOffsetVar)> { + fn get_assignment<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + e: &Expr, + var: DefId, + ) -> Option<(FixedOffsetVar, FixedOffsetVar)> { + if let Expr_::ExprAssign(ref lhs, ref rhs) = e.node { + match (get_fixed_offset_var(cx, lhs, var), get_fixed_offset_var(cx, rhs, var)) { + (Some(offset_left), Some(offset_right)) => Some((offset_left, offset_right)), + _ => None, + } + } else { + None + } + } + + if let Expr_::ExprBlock(ref b) = body.node { + let Block { + ref stmts, + ref expr, + .. + } = **b; + + stmts + .iter() + .map(|stmt| match stmt.node { + Stmt_::StmtDecl(..) => None, + Stmt_::StmtExpr(ref e, _node_id) | Stmt_::StmtSemi(ref e, _node_id) => Some(get_assignment(cx, e, var)), + }) + .chain( + expr.as_ref() + .into_iter() + .map(|e| Some(get_assignment(cx, &*e, var))), + ) + .filter_map(|op| op) + .collect::>>() + .unwrap_or_else(|| vec![]) + } else { + get_assignment(cx, body, var).into_iter().collect() + } +} + +/// Check for for loops that sequentially copy items from one slice-like +/// object to another. +fn detect_manual_memcpy<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + pat: &'tcx Pat, + arg: &'tcx Expr, + body: &'tcx Expr, + expr: &'tcx Expr, +) { + if let Some(higher::Range { + start: Some(start), + ref end, + limits, + }) = higher::range(arg) + { + // the var must be a single name + if let PatKind::Binding(_, def_id, _, _) = pat.node { + let print_sum = |arg1: &Offset, arg2: &Offset| -> String { + match (&arg1.value[..], arg1.negate, &arg2.value[..], arg2.negate) { + ("0", _, "0", _) => "".into(), + ("0", _, x, false) | (x, false, "0", false) => x.into(), + ("0", _, x, true) | (x, false, "0", true) => format!("-{}", x), + (x, false, y, false) => format!("({} + {})", x, y), + (x, false, y, true) => format!("({} - {})", x, y), + (x, true, y, false) => format!("({} - {})", y, x), + (x, true, y, true) => format!("-({} + {})", x, y), + } + }; + + let print_limit = |end: &Option<&Expr>, offset: Offset, var_name: &str| if let Some(end) = *end { + if_let_chain! {[ + let ExprMethodCall(ref method, _, ref len_args) = end.node, + method.name == "len", + len_args.len() == 1, + let Some(arg) = len_args.get(0), + snippet(cx, arg.span, "??") == var_name, + ], { + return if offset.negate { + format!("({} - {})", snippet(cx, end.span, ".len()"), offset.value) + } else { + "".to_owned() + }; + }} + + let end_str = match limits { + ast::RangeLimits::Closed => { + let end = sugg::Sugg::hir(cx, end, ""); + format!("{}", end + sugg::ONE) + }, + ast::RangeLimits::HalfOpen => format!("{}", snippet(cx, end.span, "..")), + }; + + print_sum(&Offset::positive(end_str), &offset) + } else { + "..".into() + }; + + // The only statements in the for loops can be indexed assignments from + // indexed retrievals. + let manual_copies = get_indexed_assignments(cx, body, def_id); + + let big_sugg = manual_copies + .into_iter() + .map(|(dst_var, src_var)| { + let start_str = Offset::positive(snippet_opt(cx, start.span).unwrap_or_else(|| "".into())); + let dst_offset = print_sum(&start_str, &dst_var.offset); + let dst_limit = print_limit(end, dst_var.offset, &dst_var.var_name); + let src_offset = print_sum(&start_str, &src_var.offset); + let src_limit = print_limit(end, src_var.offset, &src_var.var_name); + let dst = if dst_offset == "" && dst_limit == "" { + dst_var.var_name + } else { + format!("{}[{}..{}]", dst_var.var_name, dst_offset, dst_limit) + }; + + format!("{}.clone_from_slice(&{}[{}..{}])", dst, src_var.var_name, src_offset, src_limit) + }) + .join("\n "); + + if !big_sugg.is_empty() { + span_lint_and_sugg( + cx, + MANUAL_MEMCPY, + expr.span, + "it looks like you're manually copying between slices", + "try replacing the loop by", + big_sugg, + ); + } + } + } } /// Check for looping over a range and then indexing a sequence with it. @@ -1024,9 +1288,29 @@ impl<'tcx> Visitor<'tcx> for UsedVisitor { fn visit_expr(&mut self, expr: &'tcx Expr) { if match_var(expr, self.var) { self.used = true; - return; + } else { + walk_expr(self, expr); + } + } + + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { + NestedVisitorMap::None + } +} + +struct DefIdUsedVisitor<'a, 'tcx: 'a> { + cx: &'a LateContext<'a, 'tcx>, + def_id: DefId, + used: bool, +} + +impl<'a, 'tcx: 'a> Visitor<'tcx> for DefIdUsedVisitor<'a, 'tcx> { + fn visit_expr(&mut self, expr: &'tcx Expr) { + if same_var(self.cx, expr, self.def_id) { + self.used = true; + } else { + walk_expr(self, expr); } - walk_expr(self, expr); } fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { @@ -1054,40 +1338,46 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { if_let_chain! {[ // an index op let ExprIndex(ref seqexpr, ref idx) = expr.node, - // directly indexing a variable - let ExprPath(ref qpath) = idx.node, - let QPath::Resolved(None, ref path) = *qpath, - path.segments.len() == 1, - // our variable! - self.cx.tables.qpath_def(qpath, expr.hir_id).def_id() == self.var, // the indexed container is referenced by a name let ExprPath(ref seqpath) = seqexpr.node, let QPath::Resolved(None, ref seqvar) = *seqpath, seqvar.segments.len() == 1, ], { - let def = self.cx.tables.qpath_def(seqpath, seqexpr.hir_id); - match def { - Def::Local(..) | Def::Upvar(..) => { - let def_id = def.def_id(); - let node_id = self.cx.tcx.hir.as_local_node_id(def_id).expect("local/upvar are local nodes"); - let hir_id = self.cx.tcx.hir.node_to_hir_id(node_id); + let index_used = same_var(self.cx, idx, self.var) || { + let mut used_visitor = DefIdUsedVisitor { + cx: self.cx, + def_id: self.var, + used: false, + }; + walk_expr(&mut used_visitor, idx); + used_visitor.used + }; - let parent_id = self.cx.tcx.hir.get_parent(expr.id); - let parent_def_id = self.cx.tcx.hir.local_def_id(parent_id); - let extent = self.cx.tcx.region_scope_tree(parent_def_id).var_scope(hir_id.local_id); - self.indexed.insert(seqvar.segments[0].name, Some(extent)); - return; // no need to walk further + if index_used { + let def = self.cx.tables.qpath_def(seqpath, seqexpr.hir_id); + match def { + Def::Local(..) | Def::Upvar(..) => { + let def_id = def.def_id(); + let node_id = self.cx.tcx.hir.as_local_node_id(def_id).expect("local/upvar are local nodes"); + let hir_id = self.cx.tcx.hir.node_to_hir_id(node_id); + + let parent_id = self.cx.tcx.hir.get_parent(expr.id); + let parent_def_id = self.cx.tcx.hir.local_def_id(parent_id); + let extent = self.cx.tcx.region_scope_tree(parent_def_id).var_scope(hir_id.local_id); + self.indexed.insert(seqvar.segments[0].name, Some(extent)); + return; // no need to walk further *on the variable* + } + Def::Static(..) | Def::Const(..) => { + self.indexed.insert(seqvar.segments[0].name, None); + return; // no need to walk further *on the variable* + } + _ => (), } - Def::Static(..) | Def::Const(..) => { - self.indexed.insert(seqvar.segments[0].name, None); - return; // no need to walk further - } - _ => (), } }} if_let_chain! {[ - // directly indexing a variable + // directly using a variable let ExprPath(ref qpath) = expr.node, let QPath::Resolved(None, ref path) = *qpath, path.segments.len() == 1, diff --git a/tests/ui/for_loop.stderr b/tests/ui/for_loop.stderr index 090caf1779a5..721b2833dec2 100644 --- a/tests/ui/for_loop.stderr +++ b/tests/ui/for_loop.stderr @@ -505,57 +505,78 @@ help: use the corresponding method 409 | for k in rm.keys() { | ^ -error: the loop variable `i` is used to index `src` +error: it looks like you're manually copying between slices + --> $DIR/for_loop.rs:462:5 + | +462 | / for i in 0..src.len() { +463 | | dst[i] = src[i]; +464 | | } + | |_____^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[..])` + | + = note: `-D manual-memcpy` implied by `-D warnings` + +error: it looks like you're manually copying between slices --> $DIR/for_loop.rs:467:5 | 467 | / for i in 0..src.len() { 468 | | dst[i + 10] = src[i]; 469 | | } - | |_____^ - | -help: consider using an iterator - | -467 | for (i, ) in src.iter().enumerate() { - | ^^^^^^^^^^^ + | |_____^ help: try replacing the loop by: `dst[10..(src.len() + 10)].clone_from_slice(&src[..])` -error: the loop variable `i` is used to index `dst` +error: it looks like you're manually copying between slices --> $DIR/for_loop.rs:472:5 | 472 | / for i in 0..src.len() { 473 | | dst[i] = src[i + 10]; 474 | | } - | |_____^ - | -help: consider using an iterator - | -472 | for (i, ) in dst.iter().enumerate().take(src.len()) { - | ^^^^^^^^^^^ + | |_____^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[10..])` -error: the loop variable `i` is used to index `dst` +error: it looks like you're manually copying between slices --> $DIR/for_loop.rs:477:5 | 477 | / for i in 11..src.len() { 478 | | dst[i] = src[i - 10]; 479 | | } + | |_____^ help: try replacing the loop by: `dst[11..src.len()].clone_from_slice(&src[(11 - 10)..(src.len() - 10)])` + +error: it looks like you're manually copying between slices + --> $DIR/for_loop.rs:482:5 + | +482 | / for i in 0..dst.len() { +483 | | dst[i] = src[i]; +484 | | } + | |_____^ help: try replacing the loop by: `dst.clone_from_slice(&src[..dst.len()])` + +error: it looks like you're manually copying between slices + --> $DIR/for_loop.rs:495:5 + | +495 | / for i in 10..256 { +496 | | dst[i] = src[i - 5]; +497 | | dst2[i + 500] = src[i] +498 | | } | |_____^ | -help: consider using an iterator +help: try replacing the loop by + | +495 | dst[10..256].clone_from_slice(&src[(10 - 5)..(256 - 5)]) +496 | dst2[(10 + 500)..(256 + 500)].clone_from_slice(&src[10..256]) | -477 | for (i, ) in dst.iter().enumerate().take(src.len()).skip(11) { - | ^^^^^^^^^^^ -error: the loop variable `i` is used to index `src` - --> $DIR/for_loop.rs:512:5 +error: it looks like you're manually copying between slices + --> $DIR/for_loop.rs:507:5 | -512 | / for i in 0..10 { -513 | | dst[i + i] = src[i]; -514 | | } - | |_____^ - | -help: consider using an iterator - | -512 | for (i, ) in src.iter().enumerate().take(10) { - | ^^^^^^^^^^^ +507 | / for i in 10..LOOP_OFFSET { +508 | | dst[i + LOOP_OFFSET] = src[i - some_var]; +509 | | } + | |_____^ help: try replacing the loop by: `dst[(10 + LOOP_OFFSET)..(LOOP_OFFSET + LOOP_OFFSET)].clone_from_slice(&src[(10 - some_var)..(LOOP_OFFSET - some_var)])` -error: aborting due to 54 previous errors +error: it looks like you're manually copying between slices + --> $DIR/for_loop.rs:520:5 + | +520 | / for i in 0..src_vec.len() { +521 | | dst_vec[i] = src_vec[i]; +522 | | } + | |_____^ help: try replacing the loop by: `dst_vec[..src_vec.len()].clone_from_slice(&src_vec[..])` + +error: aborting due to 58 previous errors