parent
cca6eb2e2b
commit
90453fd893
|
@ -38,7 +38,7 @@ declare_restriction_lint! {
|
|||
|
||||
#[derive(Copy, Clone, Default)]
|
||||
pub struct Arithmetic {
|
||||
span: Option<Span>
|
||||
span: Option<Span>,
|
||||
}
|
||||
|
||||
impl LintPass for Arithmetic {
|
||||
|
@ -49,48 +49,36 @@ impl LintPass for Arithmetic {
|
|||
|
||||
impl LateLintPass for Arithmetic {
|
||||
fn check_expr(&mut self, cx: &LateContext, expr: &hir::Expr) {
|
||||
if let Some(_) = self.span { return; }
|
||||
if let Some(_) = self.span {
|
||||
return;
|
||||
}
|
||||
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.tcx.expr_ty(l), cx.tcx.expr_ty(r));
|
||||
if l_ty.is_integral() && r_ty.is_integral() {
|
||||
span_lint(cx,
|
||||
INTEGER_ARITHMETIC,
|
||||
expr.span,
|
||||
"integer arithmetic detected");
|
||||
span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
|
||||
self.span = Some(expr.span);
|
||||
} else if l_ty.is_floating_point() && r_ty.is_floating_point() {
|
||||
span_lint(cx,
|
||||
FLOAT_ARITHMETIC,
|
||||
expr.span,
|
||||
"floating-point arithmetic detected");
|
||||
span_lint(cx, FLOAT_ARITHMETIC, expr.span, "floating-point arithmetic detected");
|
||||
self.span = Some(expr.span);
|
||||
}
|
||||
},
|
||||
}
|
||||
hir::ExprUnary(hir::UnOp::UnNeg, ref arg) => {
|
||||
let ty = cx.tcx.expr_ty(arg);
|
||||
if ty.is_integral() {
|
||||
span_lint(cx,
|
||||
INTEGER_ARITHMETIC,
|
||||
expr.span,
|
||||
"integer arithmetic detected");
|
||||
span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
|
||||
self.span = Some(expr.span);
|
||||
} else if ty.is_floating_point() {
|
||||
span_lint(cx,
|
||||
FLOAT_ARITHMETIC,
|
||||
expr.span,
|
||||
"floating-point arithmetic detected");
|
||||
span_lint(cx, FLOAT_ARITHMETIC, expr.span, "floating-point arithmetic detected");
|
||||
self.span = Some(expr.span);
|
||||
}
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -79,11 +79,11 @@ impl LateLintPass for ArrayIndexing {
|
|||
// Index is a constant range
|
||||
if let Some(range) = utils::unsugar_range(index) {
|
||||
let start = range.start
|
||||
.map(|start| eval_const_expr_partial(cx.tcx, start, ExprTypeChecked, None))
|
||||
.map(|v| v.ok());
|
||||
.map(|start| eval_const_expr_partial(cx.tcx, start, ExprTypeChecked, None))
|
||||
.map(|v| v.ok());
|
||||
let end = range.end
|
||||
.map(|end| eval_const_expr_partial(cx.tcx, end, ExprTypeChecked, None))
|
||||
.map(|v| v.ok());
|
||||
.map(|end| eval_const_expr_partial(cx.tcx, end, ExprTypeChecked, None))
|
||||
.map(|v| v.ok());
|
||||
|
||||
if let Some((start, end)) = to_const_range(start, end, range.limits, size) {
|
||||
if start > size || end > size {
|
||||
|
|
|
@ -51,31 +51,24 @@ impl LateLintPass for AssignOps {
|
|||
match expr.node {
|
||||
hir::ExprAssignOp(op, ref lhs, ref rhs) => {
|
||||
if let (Some(l), Some(r)) = (snippet_opt(cx, lhs.span), snippet_opt(cx, rhs.span)) {
|
||||
span_lint_and_then(cx,
|
||||
ASSIGN_OPS,
|
||||
expr.span,
|
||||
"assign operation detected",
|
||||
|db| {
|
||||
match rhs.node {
|
||||
hir::ExprBinary(op2, _, _) if op2 != op => {
|
||||
db.span_suggestion(expr.span,
|
||||
"replace it with",
|
||||
format!("{} = {} {} ({})", l, l, op.node.as_str(), r));
|
||||
},
|
||||
_ => {
|
||||
db.span_suggestion(expr.span,
|
||||
"replace it with",
|
||||
format!("{} = {} {} {}", l, l, op.node.as_str(), r));
|
||||
}
|
||||
}
|
||||
});
|
||||
span_lint_and_then(cx, ASSIGN_OPS, expr.span, "assign operation detected", |db| {
|
||||
match rhs.node {
|
||||
hir::ExprBinary(op2, _, _) if op2 != op => {
|
||||
db.span_suggestion(expr.span,
|
||||
"replace it with",
|
||||
format!("{} = {} {} ({})", l, l, op.node.as_str(), r));
|
||||
}
|
||||
_ => {
|
||||
db.span_suggestion(expr.span,
|
||||
"replace it with",
|
||||
format!("{} = {} {} {}", l, l, op.node.as_str(), r));
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
span_lint(cx,
|
||||
ASSIGN_OPS,
|
||||
expr.span,
|
||||
"assign operation detected");
|
||||
span_lint(cx, ASSIGN_OPS, expr.span, "assign operation detected");
|
||||
}
|
||||
},
|
||||
}
|
||||
hir::ExprAssign(ref assignee, ref e) => {
|
||||
if let hir::ExprBinary(op, ref l, ref r) = e.node {
|
||||
let lint = |assignee: &hir::Expr, rhs: &hir::Expr| {
|
||||
|
@ -104,28 +97,32 @@ impl LateLintPass for AssignOps {
|
|||
}
|
||||
}
|
||||
}
|
||||
if ops!(op.node, cx, ty, rty, Add:BiAdd,
|
||||
Sub:BiSub,
|
||||
Mul:BiMul,
|
||||
Div:BiDiv,
|
||||
Rem:BiRem,
|
||||
And:BiAnd,
|
||||
Or:BiOr,
|
||||
BitAnd:BiBitAnd,
|
||||
BitOr:BiBitOr,
|
||||
BitXor:BiBitXor,
|
||||
Shr:BiShr,
|
||||
Shl:BiShl
|
||||
) {
|
||||
if let (Some(snip_a), Some(snip_r)) = (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span)) {
|
||||
if ops!(op.node,
|
||||
cx,
|
||||
ty,
|
||||
rty,
|
||||
Add: BiAdd,
|
||||
Sub: BiSub,
|
||||
Mul: BiMul,
|
||||
Div: BiDiv,
|
||||
Rem: BiRem,
|
||||
And: BiAnd,
|
||||
Or: BiOr,
|
||||
BitAnd: BiBitAnd,
|
||||
BitOr: BiBitOr,
|
||||
BitXor: BiBitXor,
|
||||
Shr: BiShr,
|
||||
Shl: BiShl) {
|
||||
if let (Some(snip_a), Some(snip_r)) = (snippet_opt(cx, assignee.span),
|
||||
snippet_opt(cx, rhs.span)) {
|
||||
span_lint_and_then(cx,
|
||||
ASSIGN_OP_PATTERN,
|
||||
expr.span,
|
||||
"manual implementation of an assign operation",
|
||||
|db| {
|
||||
db.span_suggestion(expr.span,
|
||||
"replace it with",
|
||||
format!("{} {}= {}", snip_a, op.node.as_str(), snip_r));
|
||||
"replace it with",
|
||||
format!("{} {}= {}", snip_a, op.node.as_str(), snip_r));
|
||||
});
|
||||
} else {
|
||||
span_lint(cx,
|
||||
|
@ -142,17 +139,16 @@ impl LateLintPass 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::BiBitOr => {
|
||||
hir::BiAdd | hir::BiMul | hir::BiAnd | hir::BiOr | hir::BiBitXor | hir::BiBitAnd |
|
||||
hir::BiBitOr => {
|
||||
lint(assignee, l);
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -322,7 +322,8 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> {
|
|||
let simplified_stats = terminal_stats(suggestion);
|
||||
let mut improvement = false;
|
||||
for i in 0..32 {
|
||||
// ignore any "simplifications" that end up requiring a terminal more often than in the original expression
|
||||
// ignore any "simplifications" that end up requiring a terminal more often
|
||||
// than in the original expression
|
||||
if stats.terminals[i] < simplified_stats.terminals[i] {
|
||||
continue 'simplified;
|
||||
}
|
||||
|
@ -332,17 +333,18 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> {
|
|||
e.span,
|
||||
"this boolean expression contains a logic bug",
|
||||
|db| {
|
||||
db.span_help(h2q.terminals[i].span,
|
||||
"this expression can be optimized out by applying \
|
||||
boolean operations to the outer expression");
|
||||
db.span_suggestion(e.span,
|
||||
"it would look like the following",
|
||||
suggest(self.0, suggestion, &h2q.terminals));
|
||||
});
|
||||
db.span_help(h2q.terminals[i].span,
|
||||
"this expression can be optimized out by applying boolean operations to the \
|
||||
outer expression");
|
||||
db.span_suggestion(e.span,
|
||||
"it would look like the following",
|
||||
suggest(self.0, suggestion, &h2q.terminals));
|
||||
});
|
||||
// don't also lint `NONMINIMAL_BOOL`
|
||||
return;
|
||||
}
|
||||
// if the number of occurrences of a terminal decreases or any of the stats decreases while none increases
|
||||
// if the number of occurrences of a terminal decreases or any of the stats
|
||||
// decreases while none increases
|
||||
improvement |= (stats.terminals[i] > simplified_stats.terminals[i]) ||
|
||||
(stats.negations > simplified_stats.negations &&
|
||||
stats.ops == simplified_stats.ops) ||
|
||||
|
@ -358,12 +360,10 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> {
|
|||
e.span,
|
||||
"this boolean expression can be simplified",
|
||||
|db| {
|
||||
for suggestion in &improvements {
|
||||
db.span_suggestion(e.span,
|
||||
"try",
|
||||
suggest(self.0, suggestion, &h2q.terminals));
|
||||
}
|
||||
});
|
||||
for suggestion in &improvements {
|
||||
db.span_suggestion(e.span, "try", suggest(self.0, suggestion, &h2q.terminals));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,8 @@ use utils::{in_macro, LimitStack, span_help_and_lint, paths, match_type};
|
|||
|
||||
/// **What it does:** This lint checks for methods with high cyclomatic complexity
|
||||
///
|
||||
/// **Why is this bad?** Methods of high cyclomatic complexity tend to be badly readable. Also LLVM will usually optimize small methods better.
|
||||
/// **Why is this bad?** Methods of high cyclomatic complexity tend to be badly readable. Also LLVM
|
||||
/// will usually optimize small methods better.
|
||||
///
|
||||
/// **Known problems:** Sometimes it's hard to find a way to reduce the complexity
|
||||
///
|
||||
|
@ -69,7 +70,7 @@ impl CyclomaticComplexity {
|
|||
returns / 2
|
||||
};
|
||||
|
||||
if cc + divergence < match_arms + short_circuits {
|
||||
if cc + divergence < match_arms + short_circuits {
|
||||
report_cc_bug(cx, cc, match_arms, divergence, short_circuits, ret_adjust, span);
|
||||
} else {
|
||||
let mut rust_cc = cc + divergence - match_arms - short_circuits;
|
||||
|
@ -117,7 +118,7 @@ impl LateLintPass for CyclomaticComplexity {
|
|||
}
|
||||
}
|
||||
|
||||
struct CCHelper<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||
struct CCHelper<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
|
||||
match_arms: u64,
|
||||
divergence: u64,
|
||||
returns: u64,
|
||||
|
@ -176,8 +177,9 @@ fn report_cc_bug(cx: &LateContext, cc: u64, narms: u64, div: u64, shorts: u64, r
|
|||
if cx.current_level(CYCLOMATIC_COMPLEXITY) != Level::Allow {
|
||||
cx.sess().span_note_without_error(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,
|
||||
|
|
|
@ -84,7 +84,8 @@ impl LateLintPass for Derive {
|
|||
}
|
||||
|
||||
/// Implementation of the `DERIVE_HASH_XOR_EQ` lint.
|
||||
fn check_hash_peq<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, span: Span, trait_ref: &TraitRef, ty: ty::Ty<'tcx>, hash_is_automatically_derived: bool) {
|
||||
fn check_hash_peq<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, span: Span, trait_ref: &TraitRef, ty: ty::Ty<'tcx>,
|
||||
hash_is_automatically_derived: bool) {
|
||||
if_let_chain! {[
|
||||
match_path(&trait_ref.path, &paths::HASH),
|
||||
let Some(peq_trait_def_id) = cx.tcx.lang_items.eq_trait()
|
||||
|
@ -137,7 +138,8 @@ fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, item: &Item, trait_ref
|
|||
|
||||
// Some types are not Clone by default but could be cloned `by hand` if necessary
|
||||
match ty.sty {
|
||||
TypeVariants::TyEnum(def, substs) | TypeVariants::TyStruct(def, substs) => {
|
||||
TypeVariants::TyEnum(def, substs) |
|
||||
TypeVariants::TyStruct(def, substs) => {
|
||||
for variant in &def.variants {
|
||||
for field in &variant.fields {
|
||||
match field.ty(cx.tcx, substs).sty {
|
||||
|
|
|
@ -108,7 +108,7 @@ pub fn check_doc(cx: &EarlyContext, valid_idents: &[String], docs: &[(&str, Span
|
|||
/// First byte of the current potential match
|
||||
current_word_begin: usize,
|
||||
/// List of lines and their associated span
|
||||
docs: &'a[(&'a str, Span)],
|
||||
docs: &'a [(&'a str, Span)],
|
||||
/// Index of the current line we are parsing
|
||||
line: usize,
|
||||
/// Whether we are in a link
|
||||
|
|
|
@ -42,7 +42,8 @@ impl LintPass for Functions {
|
|||
}
|
||||
|
||||
impl LateLintPass for Functions {
|
||||
fn check_fn(&mut self, cx: &LateContext, _: intravisit::FnKind, decl: &hir::FnDecl, _: &hir::Block, span: Span, nodeid: ast::NodeId) {
|
||||
fn check_fn(&mut self, cx: &LateContext, _: intravisit::FnKind, decl: &hir::FnDecl, _: &hir::Block, span: Span,
|
||||
nodeid: ast::NodeId) {
|
||||
use rustc::hir::map::Node::*;
|
||||
|
||||
if let Some(NodeItem(ref item)) = cx.tcx.map.find(cx.tcx.map.get_parent_node(nodeid)) {
|
||||
|
|
|
@ -182,7 +182,7 @@ fn used_in_expr(cx: &LateContext, id: hir::def_id::DefId, expr: &hir::Expr) -> b
|
|||
let mut v = UsedVisitor {
|
||||
cx: cx,
|
||||
id: id,
|
||||
used: false
|
||||
used: false,
|
||||
};
|
||||
hir::intravisit::walk_expr(&mut v, expr);
|
||||
v.used
|
||||
|
|
|
@ -608,13 +608,13 @@ fn check_for_loop_over_map_kv(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Ex
|
|||
expr.span,
|
||||
&format!("you seem to want to iterate on a map's {}", kind),
|
||||
|db| {
|
||||
db.span_suggestion(expr.span,
|
||||
"use the corresponding method",
|
||||
format!("for {} in {}.{}() {{ .. }}",
|
||||
snippet(cx, *pat_span, ".."),
|
||||
snippet(cx, arg_span, ".."),
|
||||
kind));
|
||||
});
|
||||
db.span_suggestion(expr.span,
|
||||
"use the corresponding method",
|
||||
format!("for {} in {}.{}() {{ .. }}",
|
||||
snippet(cx, *pat_span, ".."),
|
||||
snippet(cx, arg_span, ".."),
|
||||
kind));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -171,14 +171,14 @@ fn check_single_match_single_pattern(cx: &LateContext, ex: &Expr, arms: &[Arm],
|
|||
"you seem to be trying to use match for destructuring a single pattern. \
|
||||
Consider using `if let`",
|
||||
|db| {
|
||||
db.span_suggestion(expr.span,
|
||||
"try this",
|
||||
format!("if let {} = {} {}{}",
|
||||
snippet(cx, arms[0].pats[0].span, ".."),
|
||||
snippet(cx, ex.span, ".."),
|
||||
expr_block(cx, &arms[0].body, None, ".."),
|
||||
els_str));
|
||||
});
|
||||
db.span_suggestion(expr.span,
|
||||
"try this",
|
||||
format!("if let {} = {} {}{}",
|
||||
snippet(cx, arms[0].pats[0].span, ".."),
|
||||
snippet(cx, ex.span, ".."),
|
||||
expr_block(cx, &arms[0].body, None, ".."),
|
||||
els_str));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -219,14 +219,14 @@ fn check_single_match_opt_like(cx: &LateContext, ex: &Expr, arms: &[Arm], expr:
|
|||
"you seem to be trying to use match for destructuring a single pattern. Consider \
|
||||
using `if let`",
|
||||
|db| {
|
||||
db.span_suggestion(expr.span,
|
||||
"try this",
|
||||
format!("if let {} = {} {}{}",
|
||||
snippet(cx, arms[0].pats[0].span, ".."),
|
||||
snippet(cx, ex.span, ".."),
|
||||
expr_block(cx, &arms[0].body, None, ".."),
|
||||
els_str));
|
||||
});
|
||||
db.span_suggestion(expr.span,
|
||||
"try this",
|
||||
format!("if let {} = {} {}{}",
|
||||
snippet(cx, arms[0].pats[0].span, ".."),
|
||||
snippet(cx, ex.span, ".."),
|
||||
expr_block(cx, &arms[0].body, None, ".."),
|
||||
els_str));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ impl LateLintPass for MemForget {
|
|||
|
||||
if match forgot_ty.ty_adt_def() {
|
||||
Some(def) => def.has_dtor(),
|
||||
_ => false
|
||||
_ => false,
|
||||
} {
|
||||
span_lint(cx, MEM_FORGET, e.span, "usage of mem::forget on Drop type");
|
||||
}
|
||||
|
|
|
@ -452,8 +452,8 @@ impl LateLintPass for MethodsPass {
|
|||
explicit_self.span,
|
||||
"methods called `new` usually return `Self`");
|
||||
}
|
||||
}
|
||||
}}
|
||||
}}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1022,9 +1022,7 @@ impl OutType {
|
|||
(&OutType::Unit, &hir::Return(ref ty)) if ty.node == hir::TyTup(vec![].into()) => true,
|
||||
(&OutType::Bool, &hir::Return(ref ty)) if is_bool(ty) => true,
|
||||
(&OutType::Any, &hir::Return(ref ty)) if ty.node != hir::TyTup(vec![].into()) => true,
|
||||
(&OutType::Ref, &hir::Return(ref ty)) => {
|
||||
matches!(ty.node, hir::TyRptr(_, _))
|
||||
}
|
||||
(&OutType::Ref, &hir::Return(ref ty)) => matches!(ty.node, hir::TyRptr(_, _)),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,10 +34,7 @@ impl LateLintPass for MutMut {
|
|||
|
||||
if let ExprAddrOf(MutMutable, ref e) = expr.node {
|
||||
if let ExprAddrOf(MutMutable, _) = e.node {
|
||||
span_lint(cx,
|
||||
MUT_MUT,
|
||||
expr.span,
|
||||
"generally you want to avoid `&mut &mut _` if possible");
|
||||
span_lint(cx, MUT_MUT, expr.span, "generally you want to avoid `&mut &mut _` if possible");
|
||||
} else {
|
||||
if let TyRef(_, TypeAndMut { mutbl: MutMutable, .. }) = cx.tcx.expr_ty(e).sty {
|
||||
span_lint(cx,
|
||||
|
|
|
@ -42,7 +42,8 @@ impl LateLintPass for NeedlessBorrow {
|
|||
span_lint(cx,
|
||||
NEEDLESS_BORROW,
|
||||
e.span,
|
||||
"this expression borrows a reference that is immediately dereferenced by the compiler");
|
||||
"this expression borrows a reference that is immediately dereferenced by the \
|
||||
compiler");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ impl LateLintPass for NegMultiply {
|
|||
(&ExprUnary(..), &ExprUnary(..)) => (),
|
||||
(&ExprUnary(UnNeg, ref lit), _) => check_mul(cx, e.span, lit, r),
|
||||
(_, &ExprUnary(UnNeg, ref lit)) => check_mul(cx, e.span, lit, l),
|
||||
_ => ()
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -100,10 +100,10 @@ impl LateLintPass for NewWithoutDefault {
|
|||
// can't be implemented by default
|
||||
return;
|
||||
}
|
||||
if decl.inputs.is_empty() && name.as_str() == "new" &&
|
||||
cx.access_levels.is_reachable(id) {
|
||||
let self_ty = cx.tcx.lookup_item_type(cx.tcx.map.local_def_id(
|
||||
cx.tcx.map.get_parent(id))).ty;
|
||||
if decl.inputs.is_empty() && name.as_str() == "new" && cx.access_levels.is_reachable(id) {
|
||||
let self_ty = cx.tcx
|
||||
.lookup_item_type(cx.tcx.map.local_def_id(cx.tcx.map.get_parent(id)))
|
||||
.ty;
|
||||
if_let_chain!{[
|
||||
self_ty.walk_shallow().next().is_none(), // implements_trait does not work with generics
|
||||
let Some(ret_ty) = return_ty(cx, id),
|
||||
|
@ -143,11 +143,11 @@ fn can_derive_default<'t, 'c>(ty: ty::Ty<'t>, cx: &LateContext<'c, 't>, default_
|
|||
for field in adt_def.all_fields() {
|
||||
let f_ty = field.ty(cx.tcx, substs);
|
||||
if !implements_trait(cx, f_ty, default_trait_id, Vec::new()) {
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
},
|
||||
_ => false
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -130,7 +130,9 @@ fn reduce_expression<'a>(cx: &LateContext, expr: &'a Expr) -> Option<Vec<&'a Exp
|
|||
Expr_::ExprTupField(ref inner, _) |
|
||||
Expr_::ExprAddrOf(_, ref inner) |
|
||||
Expr_::ExprBox(ref inner) => 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_::ExprStruct(_, ref fields, ref base) => {
|
||||
Some(fields.iter().map(|f| &f.expr).chain(base).map(Deref::deref).collect())
|
||||
}
|
||||
Expr_::ExprCall(ref callee, ref args) => {
|
||||
match cx.tcx.def_map.borrow().get(&callee.id).map(PathResolution::full_def) {
|
||||
Some(Def::Struct(..)) |
|
||||
|
@ -140,11 +142,13 @@ fn reduce_expression<'a>(cx: &LateContext, expr: &'a Expr) -> Option<Vec<&'a Exp
|
|||
}
|
||||
Expr_::ExprBlock(ref block) => {
|
||||
if block.stmts.is_empty() {
|
||||
block.expr.as_ref().and_then(|e| match block.rules {
|
||||
BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) => None,
|
||||
BlockCheckMode::DefaultBlock => Some(vec![&**e]),
|
||||
// in case of compiler-inserted signaling blocks
|
||||
_ => reduce_expression(cx, e),
|
||||
block.expr.as_ref().and_then(|e| {
|
||||
match block.rules {
|
||||
BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) => None,
|
||||
BlockCheckMode::DefaultBlock => Some(vec![&**e]),
|
||||
// in case of compiler-inserted signaling blocks
|
||||
_ => reduce_expression(cx, e),
|
||||
}
|
||||
})
|
||||
} else {
|
||||
None
|
||||
|
|
|
@ -72,11 +72,13 @@ impl<'v, 'a, 'b, 'c> Visitor<'v> for SimilarNamesNameVisitor<'a, 'b, 'c> {
|
|||
fn visit_pat(&mut self, pat: &'v 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),
|
||||
}
|
||||
}
|
||||
|
@ -193,15 +195,15 @@ impl<'a, 'b, 'c> SimilarNamesNameVisitor<'a, 'b, 'c> {
|
|||
span,
|
||||
"binding's name is too similar to existing binding",
|
||||
|diag| {
|
||||
diag.span_note(existing_name.span, "existing binding defined here");
|
||||
if let Some(split) = split_at {
|
||||
diag.span_help(span,
|
||||
&format!("separate the discriminating character by an \
|
||||
diag.span_note(existing_name.span, "existing binding defined here");
|
||||
if let Some(split) = split_at {
|
||||
diag.span_help(span,
|
||||
&format!("separate the discriminating character by an \
|
||||
underscore like: `{}_{}`",
|
||||
&interned_name[..split],
|
||||
&interned_name[split..]));
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
self.0.names.push(ExistingName {
|
||||
|
|
|
@ -125,7 +125,7 @@ impl LateLintPass for RegexPass {
|
|||
fn str_span(base: Span, s: &str, c: usize) -> Span {
|
||||
let mut si = s.char_indices().skip(c);
|
||||
|
||||
match (si.next(), si.next()) {
|
||||
match (si.next(), si.next()) {
|
||||
(Some((l, _)), Some((h, _))) => {
|
||||
Span {
|
||||
lo: base.lo + BytePos(l as u32),
|
||||
|
@ -193,7 +193,9 @@ fn check_regex(cx: &LateContext, expr: &Expr, utf8: bool) {
|
|||
match builder.parse(r) {
|
||||
Ok(r) => {
|
||||
if let Some(repl) = is_trivial_regex(&r) {
|
||||
span_help_and_lint(cx, TRIVIAL_REGEX, expr.span,
|
||||
span_help_and_lint(cx,
|
||||
TRIVIAL_REGEX,
|
||||
expr.span,
|
||||
"trivial regex",
|
||||
&format!("consider using {}", repl));
|
||||
}
|
||||
|
@ -211,7 +213,9 @@ fn check_regex(cx: &LateContext, expr: &Expr, utf8: bool) {
|
|||
match builder.parse(&r) {
|
||||
Ok(r) => {
|
||||
if let Some(repl) = is_trivial_regex(&r) {
|
||||
span_help_and_lint(cx, TRIVIAL_REGEX, expr.span,
|
||||
span_help_and_lint(cx,
|
||||
TRIVIAL_REGEX,
|
||||
expr.span,
|
||||
"trivial regex",
|
||||
&format!("consider using {}", repl));
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ impl LateLintPass for UnsafeNameRemoval {
|
|||
*name,
|
||||
cx, &item.span
|
||||
);
|
||||
},
|
||||
}
|
||||
ViewPath_::ViewPathList(_, ref path_list_items) => {
|
||||
for path_list_item in path_list_items.iter() {
|
||||
let plid = path_list_item.node;
|
||||
|
@ -53,7 +53,7 @@ impl LateLintPass for UnsafeNameRemoval {
|
|||
unsafe_to_safe_check(name, rename, cx, &item.span);
|
||||
};
|
||||
}
|
||||
},
|
||||
}
|
||||
ViewPath_::ViewPathGlob(_) => {}
|
||||
}
|
||||
}
|
||||
|
@ -64,11 +64,10 @@ fn unsafe_to_safe_check(old_name: Name, new_name: Name, cx: &LateContext, span:
|
|||
let old_str = old_name.as_str();
|
||||
let new_str = new_name.as_str();
|
||||
if contains_unsafe(&old_str) && !contains_unsafe(&new_str) {
|
||||
span_lint(
|
||||
cx,
|
||||
UNSAFE_REMOVED_FROM_NAME,
|
||||
*span,
|
||||
&format!(
|
||||
span_lint(cx,
|
||||
UNSAFE_REMOVED_FROM_NAME,
|
||||
*span,
|
||||
&format!(
|
||||
"removed \"unsafe\" from the name of `{}` in use as `{}`",
|
||||
old_str,
|
||||
new_str
|
||||
|
|
|
@ -64,10 +64,12 @@ impl LateLintPass for UnusedLabel {
|
|||
impl<'v> Visitor<'v> for UnusedLabelVisitor {
|
||||
fn visit_expr(&mut self, expr: &hir::Expr) {
|
||||
match expr.node {
|
||||
hir::ExprBreak(Some(label)) | hir::ExprAgain(Some(label)) => {
|
||||
hir::ExprBreak(Some(label)) |
|
||||
hir::ExprAgain(Some(label)) => {
|
||||
self.labels.remove(&label.node.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);
|
||||
}
|
||||
_ => (),
|
||||
|
|
|
@ -50,13 +50,19 @@ pub enum Error {
|
|||
}
|
||||
|
||||
impl From<io::Error> for Error {
|
||||
fn from(err: io::Error) -> Self { Error::Io(err) }
|
||||
fn from(err: io::Error) -> Self {
|
||||
Error::Io(err)
|
||||
}
|
||||
}
|
||||
impl From<Utf8Error> for Error {
|
||||
fn from(err: Utf8Error) -> Self { Error::Utf8(err) }
|
||||
fn from(err: Utf8Error) -> Self {
|
||||
Error::Utf8(err)
|
||||
}
|
||||
}
|
||||
impl From<json::DecoderError> for Error {
|
||||
fn from(err: json::DecoderError) -> Self { Error::Json(err) }
|
||||
fn from(err: json::DecoderError) -> Self {
|
||||
Error::Json(err)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn metadata() -> Result<Metadata, Error> {
|
||||
|
|
|
@ -153,7 +153,9 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
|
|||
(&PatKind::QPath(ref ls, ref lp), &PatKind::QPath(ref rs, ref rp)) => {
|
||||
self.eq_qself(ls, rs) && self.eq_path(lp, rp)
|
||||
}
|
||||
(&PatKind::Tuple(ref l, ls), &PatKind::Tuple(ref r, rs)) => ls == rs && over(l, r, |l, r| self.eq_pat(l, r)),
|
||||
(&PatKind::Tuple(ref l, ls), &PatKind::Tuple(ref r, rs)) => {
|
||||
ls == rs && over(l, r, |l, r| self.eq_pat(l, r))
|
||||
}
|
||||
(&PatKind::Range(ref ls, ref le), &PatKind::Range(ref rs, ref re)) => {
|
||||
self.eq_expr(ls, rs) && self.eq_expr(le, re)
|
||||
}
|
||||
|
|
|
@ -143,9 +143,7 @@ pub fn match_def_path(cx: &LateContext, def_id: DefId, path: &[&str]) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
let mut apb = AbsolutePathBuffer {
|
||||
names: vec![],
|
||||
};
|
||||
let mut apb = AbsolutePathBuffer { names: vec![] };
|
||||
|
||||
cx.tcx.push_item_path(&mut apb, def_id);
|
||||
|
||||
|
@ -763,7 +761,8 @@ pub fn unsugar_range(expr: &Expr) -> Option<UnsugaredRange> {
|
|||
end: None,
|
||||
limits: RangeLimits::HalfOpen,
|
||||
})
|
||||
} else if match_path(path, &paths::RANGE_INCLUSIVE_NON_EMPTY_STD) || match_path(path, &paths::RANGE_INCLUSIVE_NON_EMPTY) {
|
||||
} else if match_path(path, &paths::RANGE_INCLUSIVE_NON_EMPTY_STD) ||
|
||||
match_path(path, &paths::RANGE_INCLUSIVE_NON_EMPTY) {
|
||||
Some(UnsugaredRange {
|
||||
start: get_field("start", fields),
|
||||
end: get_field("end", fields),
|
||||
|
|
32
src/main.rs
32
src/main.rs
|
@ -71,7 +71,13 @@ impl<'a> CompilerCalls<'a> for ClippyCompilerCalls {
|
|||
registry.args_hidden = Some(Vec::new());
|
||||
clippy_lints::register_plugins(&mut registry);
|
||||
|
||||
let rustc_plugin::registry::Registry { early_lint_passes, late_lint_passes, lint_groups, llvm_passes, attributes, mir_passes, .. } = registry;
|
||||
let rustc_plugin::registry::Registry { early_lint_passes,
|
||||
late_lint_passes,
|
||||
lint_groups,
|
||||
llvm_passes,
|
||||
attributes,
|
||||
mir_passes,
|
||||
.. } = registry;
|
||||
let sess = &state.session;
|
||||
let mut ls = sess.lint_store.borrow_mut();
|
||||
for pass in early_lint_passes {
|
||||
|
@ -111,14 +117,18 @@ pub fn main() {
|
|||
let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN"));
|
||||
let sys_root = match (home, toolchain) {
|
||||
(Some(home), Some(toolchain)) => format!("{}/toolchains/{}", home, toolchain),
|
||||
_ => option_env!("SYSROOT").map(|s| s.to_owned())
|
||||
.or(Command::new("rustc").arg("--print")
|
||||
.arg("sysroot")
|
||||
.output().ok()
|
||||
.and_then(|out| String::from_utf8(out.stdout).ok())
|
||||
.map(|s| s.trim().to_owned())
|
||||
)
|
||||
.expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust"),
|
||||
_ => {
|
||||
option_env!("SYSROOT")
|
||||
.map(|s| s.to_owned())
|
||||
.or(Command::new("rustc")
|
||||
.arg("--print")
|
||||
.arg("sysroot")
|
||||
.output()
|
||||
.ok()
|
||||
.and_then(|out| String::from_utf8(out.stdout).ok())
|
||||
.map(|s| s.trim().to_owned()))
|
||||
.expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust")
|
||||
}
|
||||
};
|
||||
|
||||
if let Some("clippy") = std::env::args().nth(1).as_ref().map(AsRef::as_ref) {
|
||||
|
@ -160,7 +170,9 @@ pub fn main() {
|
|||
}
|
||||
|
||||
fn process<P, I>(old_args: I, dep_path: P, sysroot: &str) -> Result<(), i32>
|
||||
where P: AsRef<Path>, I: Iterator<Item=String> {
|
||||
where P: AsRef<Path>,
|
||||
I: Iterator<Item = String>
|
||||
{
|
||||
|
||||
let mut args = vec!["rustc".to_owned()];
|
||||
|
||||
|
|
|
@ -14,7 +14,10 @@ struct Test {
|
|||
|
||||
fn main() {
|
||||
use Baz::*;
|
||||
let x = Test { t: Some(0), b: One };
|
||||
let x = Test {
|
||||
t: Some(0),
|
||||
b: One,
|
||||
};
|
||||
|
||||
match x {
|
||||
Test { t: Some(_), b: One } => unreachable!(),
|
||||
|
|
|
@ -9,7 +9,7 @@ fn run_mode(dir: &'static str, mode: &'static str) {
|
|||
let cfg_mode = mode.parse().ok().expect("Invalid mode");
|
||||
config.target_rustcflags = Some("-L target/debug/ -L target/debug/deps".to_owned());
|
||||
if let Ok(name) = var::<&str>("TESTNAME") {
|
||||
let s : String = name.to_owned();
|
||||
let s: String = name.to_owned();
|
||||
config.filter = Some(s)
|
||||
}
|
||||
|
||||
|
|
|
@ -16,15 +16,18 @@ use syntax::parse::token::InternedString;
|
|||
use syntax::ptr::P;
|
||||
|
||||
fn spanned<T>(t: T) -> Spanned<T> {
|
||||
Spanned{ node: t, span: COMMAND_LINE_SP }
|
||||
Spanned {
|
||||
node: t,
|
||||
span: COMMAND_LINE_SP,
|
||||
}
|
||||
}
|
||||
|
||||
fn expr(n: Expr_) -> Expr {
|
||||
Expr{
|
||||
Expr {
|
||||
id: 1,
|
||||
node: n,
|
||||
span: COMMAND_LINE_SP,
|
||||
attrs: None
|
||||
attrs: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,19 +43,19 @@ fn check(expect: Constant, expr: &Expr) {
|
|||
assert_eq!(Some(expect), constant_simple(expr))
|
||||
}
|
||||
|
||||
const TRUE : Constant = Constant::Bool(true);
|
||||
const FALSE : Constant = Constant::Bool(false);
|
||||
const ZERO : Constant = Constant::Int(ConstInt::Infer(0));
|
||||
const ONE : Constant = Constant::Int(ConstInt::Infer(1));
|
||||
const TWO : Constant = Constant::Int(ConstInt::Infer(2));
|
||||
const TRUE: Constant = Constant::Bool(true);
|
||||
const FALSE: Constant = Constant::Bool(false);
|
||||
const ZERO: Constant = Constant::Int(ConstInt::Infer(0));
|
||||
const ONE: Constant = Constant::Int(ConstInt::Infer(1));
|
||||
const TWO: Constant = Constant::Int(ConstInt::Infer(2));
|
||||
|
||||
#[test]
|
||||
fn test_lit() {
|
||||
check(TRUE, &lit(LitKind::Bool(true)));
|
||||
check(FALSE, &lit(LitKind::Bool(false)));
|
||||
check(ZERO, &lit(LitKind::Int(0, LitIntType::Unsuffixed)));
|
||||
check(Constant::Str("cool!".into(), StrStyle::Cooked), &lit(LitKind::Str(
|
||||
InternedString::new("cool!"), StrStyle::Cooked)));
|
||||
check(Constant::Str("cool!".into(), StrStyle::Cooked),
|
||||
&lit(LitKind::Str(InternedString::new("cool!"), StrStyle::Cooked)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -30,11 +30,7 @@ fn dogfood() {
|
|||
|
||||
config.mode = cfg_mode;
|
||||
|
||||
let files = [
|
||||
"src/main.rs",
|
||||
"src/lib.rs",
|
||||
"clippy_lints/src/lib.rs",
|
||||
];
|
||||
let files = ["src/main.rs", "src/lib.rs", "clippy_lints/src/lib.rs"];
|
||||
|
||||
for file in &files {
|
||||
let paths = TestPaths {
|
||||
|
|
|
@ -22,4 +22,4 @@ fn rust_type_id(name: String) {
|
|||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
fn main() {}
|
||||
|
|
|
@ -9,7 +9,12 @@ fn test_overlapping() {
|
|||
use clippy::matches::overlapping;
|
||||
use syntax::codemap::DUMMY_SP;
|
||||
|
||||
let sp = |s, e| clippy::matches::SpannedRange { span: DUMMY_SP, node: (s, e) };
|
||||
let sp = |s, e| {
|
||||
clippy::matches::SpannedRange {
|
||||
span: DUMMY_SP,
|
||||
node: (s, e),
|
||||
}
|
||||
};
|
||||
|
||||
assert_eq!(None, overlapping::<u8>(&[]));
|
||||
assert_eq!(None, overlapping(&[sp(1, 4)]));
|
||||
|
|
|
@ -12,5 +12,5 @@ struct MacroAttributesTest {
|
|||
|
||||
#[test]
|
||||
fn macro_attributes_test() {
|
||||
let _ = MacroAttributesTest{_foo: 0};
|
||||
let _ = MacroAttributesTest { _foo: 0 };
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue