diff --git a/README.md b/README.md index fcd8d38a3b3..62367b8a26e 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,7 @@ You can add options to `allow`/`warn`/`deny`: *`deny` produces error instead of warnings* -To have cargo compile your crate with clippy without needing `#![plugin(clippy)]` +To have cargo compile your crate with clippy without needing `#![plugin(clippy)]` in your code, you can use: ``` diff --git a/src/approx_const.rs b/src/approx_const.rs index 03d4da1ab7f..3ae579a74b9 100644 --- a/src/approx_const.rs +++ b/src/approx_const.rs @@ -15,12 +15,12 @@ declare_lint! { "Warn if a user writes an approximate known constant in their code" } -const KNOWN_CONSTS : &'static [(f64, &'static str)] = &[(f64::E, "E"), (f64::FRAC_1_PI, "FRAC_1_PI"), - (f64::FRAC_1_SQRT_2, "FRAC_1_SQRT_2"), (f64::FRAC_2_PI, "FRAC_2_PI"), - (f64::FRAC_2_SQRT_PI, "FRAC_2_SQRT_PI"), (f64::FRAC_PI_2, "FRAC_PI_2"), (f64::FRAC_PI_3, "FRAC_PI_3"), - (f64::FRAC_PI_4, "FRAC_PI_4"), (f64::FRAC_PI_6, "FRAC_PI_6"), (f64::FRAC_PI_8, "FRAC_PI_8"), - (f64::LN_10, "LN_10"), (f64::LN_2, "LN_2"), (f64::LOG10_E, "LOG10_E"), (f64::LOG2_E, "LOG2_E"), - (f64::PI, "PI"), (f64::SQRT_2, "SQRT_2")]; +const KNOWN_CONSTS : &'static [(f64, &'static str)] = &[(f64::E, "E"), (f64::FRAC_1_PI, "FRAC_1_PI"), + (f64::FRAC_1_SQRT_2, "FRAC_1_SQRT_2"), (f64::FRAC_2_PI, "FRAC_2_PI"), + (f64::FRAC_2_SQRT_PI, "FRAC_2_SQRT_PI"), (f64::FRAC_PI_2, "FRAC_PI_2"), (f64::FRAC_PI_3, "FRAC_PI_3"), + (f64::FRAC_PI_4, "FRAC_PI_4"), (f64::FRAC_PI_6, "FRAC_PI_6"), (f64::FRAC_PI_8, "FRAC_PI_8"), + (f64::LN_10, "LN_10"), (f64::LN_2, "LN_2"), (f64::LOG10_E, "LOG10_E"), (f64::LOG2_E, "LOG2_E"), + (f64::PI, "PI"), (f64::SQRT_2, "SQRT_2")]; const EPSILON_DIVISOR : f64 = 8192f64; //TODO: test to find a good value @@ -31,34 +31,34 @@ impl LintPass for ApproxConstant { fn get_lints(&self) -> LintArray { lint_array!(APPROX_CONSTANT) } - + fn check_expr(&mut self, cx: &Context, e: &Expr) { - if let &ExprLit(ref lit) = &e.node { - check_lit(cx, lit, e.span); - } + if let &ExprLit(ref lit) = &e.node { + check_lit(cx, lit, e.span); + } } } fn check_lit(cx: &Context, lit: &Lit, span: Span) { - match &lit.node { - &LitFloat(ref str, TyF32) => check_known_consts(cx, span, str, "f32"), - &LitFloat(ref str, TyF64) => check_known_consts(cx, span, str, "f64"), - &LitFloatUnsuffixed(ref str) => check_known_consts(cx, span, str, "f{32, 64}"), - _ => () - } + match &lit.node { + &LitFloat(ref str, TyF32) => check_known_consts(cx, span, str, "f32"), + &LitFloat(ref str, TyF64) => check_known_consts(cx, span, str, "f64"), + &LitFloatUnsuffixed(ref str) => check_known_consts(cx, span, str, "f{32, 64}"), + _ => () + } } fn check_known_consts(cx: &Context, span: Span, str: &str, module: &str) { - if let Ok(value) = str.parse::() { - for &(constant, name) in KNOWN_CONSTS { - if within_epsilon(constant, value) { - span_lint(cx, APPROX_CONSTANT, span, &format!( - "Approximate value of {}::{} found, consider using it directly.", module, &name)); - } - } - } + if let Ok(value) = str.parse::() { + for &(constant, name) in KNOWN_CONSTS { + if within_epsilon(constant, value) { + span_lint(cx, APPROX_CONSTANT, span, &format!( + "Approximate value of {}::{} found, consider using it directly.", module, &name)); + } + } + } } fn within_epsilon(target: f64, value: f64) -> bool { - f64::abs(value - target) < f64::abs((if target > value { target } else { value })) / EPSILON_DIVISOR + f64::abs(value - target) < f64::abs((if target > value { target } else { value })) / EPSILON_DIVISOR } diff --git a/src/attrs.rs b/src/attrs.rs index 8d9e289fada..6d73f1de964 100644 --- a/src/attrs.rs +++ b/src/attrs.rs @@ -19,92 +19,92 @@ impl LintPass for AttrPass { fn get_lints(&self) -> LintArray { lint_array!(INLINE_ALWAYS) } - + fn check_item(&mut self, cx: &Context, item: &Item) { - if is_relevant_item(item) { - cx.sess().codemap().with_expn_info(item.span.expn_id, - |info| check_attrs(cx, info, &item.ident, &item.attrs)) - } - } - + if is_relevant_item(item) { + cx.sess().codemap().with_expn_info(item.span.expn_id, + |info| check_attrs(cx, info, &item.ident, &item.attrs)) + } + } + fn check_impl_item(&mut self, cx: &Context, item: &ImplItem) { - if is_relevant_impl(item) { - cx.sess().codemap().with_expn_info(item.span.expn_id, - |info| check_attrs(cx, info, &item.ident, &item.attrs)) - } - } - - fn check_trait_item(&mut self, cx: &Context, item: &TraitItem) { - if is_relevant_trait(item) { - cx.sess().codemap().with_expn_info(item.span.expn_id, - |info| check_attrs(cx, info, &item.ident, &item.attrs)) - } - } + if is_relevant_impl(item) { + cx.sess().codemap().with_expn_info(item.span.expn_id, + |info| check_attrs(cx, info, &item.ident, &item.attrs)) + } + } + + fn check_trait_item(&mut self, cx: &Context, item: &TraitItem) { + if is_relevant_trait(item) { + cx.sess().codemap().with_expn_info(item.span.expn_id, + |info| check_attrs(cx, info, &item.ident, &item.attrs)) + } + } } fn is_relevant_item(item: &Item) -> bool { - if let &ItemFn(_, _, _, _, _, ref block) = &item.node { - is_relevant_block(block) - } else { false } + if let &ItemFn(_, _, _, _, _, ref block) = &item.node { + is_relevant_block(block) + } else { false } } fn is_relevant_impl(item: &ImplItem) -> bool { - match item.node { - MethodImplItem(_, ref block) => is_relevant_block(block), - _ => false - } + match item.node { + MethodImplItem(_, ref block) => is_relevant_block(block), + _ => false + } } fn is_relevant_trait(item: &TraitItem) -> bool { - match item.node { - MethodTraitItem(_, None) => true, - MethodTraitItem(_, Some(ref block)) => is_relevant_block(block), - _ => false - } + match item.node { + MethodTraitItem(_, None) => true, + MethodTraitItem(_, Some(ref block)) => is_relevant_block(block), + _ => false + } } fn is_relevant_block(block: &Block) -> bool { - for stmt in block.stmts.iter() { - match stmt.node { - StmtDecl(_, _) => return true, - StmtExpr(ref expr, _) | StmtSemi(ref expr, _) => { - return is_relevant_expr(expr); - } - _ => () - } - } - block.expr.as_ref().map_or(false, |e| is_relevant_expr(&*e)) + for stmt in block.stmts.iter() { + match stmt.node { + StmtDecl(_, _) => return true, + StmtExpr(ref expr, _) | StmtSemi(ref expr, _) => { + return is_relevant_expr(expr); + } + _ => () + } + } + block.expr.as_ref().map_or(false, |e| is_relevant_expr(&*e)) } fn is_relevant_expr(expr: &Expr) -> bool { - match expr.node { - ExprBlock(ref block) => is_relevant_block(block), - ExprRet(Some(ref e)) | ExprParen(ref e) => - is_relevant_expr(&*e), - ExprRet(None) | ExprBreak(_) | ExprMac(_) => false, - ExprCall(ref path_expr, _) => { - if let ExprPath(_, ref path) = path_expr.node { - !match_path(path, &["std", "rt", "begin_unwind"]) - } else { true } - } - _ => true - } + match expr.node { + ExprBlock(ref block) => is_relevant_block(block), + ExprRet(Some(ref e)) | ExprParen(ref e) => + is_relevant_expr(&*e), + ExprRet(None) | ExprBreak(_) | ExprMac(_) => false, + ExprCall(ref path_expr, _) => { + if let ExprPath(_, ref path) = path_expr.node { + !match_path(path, &["std", "rt", "begin_unwind"]) + } else { true } + } + _ => true + } } -fn check_attrs(cx: &Context, info: Option<&ExpnInfo>, ident: &Ident, - attrs: &[Attribute]) { - if in_macro(cx, info) { return; } - - for attr in attrs { - if let MetaList(ref inline, ref values) = attr.node.value.node { - if values.len() != 1 || inline != &"inline" { continue; } - if let MetaWord(ref always) = values[0].node { - if always != &"always" { continue; } - span_lint(cx, INLINE_ALWAYS, attr.span, &format!( - "You have declared #[inline(always)] on {}. This \ - is usually a bad idea. Are you sure?", - ident.name.as_str())); - } - } - } +fn check_attrs(cx: &Context, info: Option<&ExpnInfo>, ident: &Ident, + attrs: &[Attribute]) { + if in_macro(cx, info) { return; } + + for attr in attrs { + if let MetaList(ref inline, ref values) = attr.node.value.node { + if values.len() != 1 || inline != &"inline" { continue; } + if let MetaWord(ref always) = values[0].node { + if always != &"always" { continue; } + span_lint(cx, INLINE_ALWAYS, attr.span, &format!( + "You have declared #[inline(always)] on {}. This \ + is usually a bad idea. Are you sure?", + ident.name.as_str())); + } + } + } } diff --git a/src/bit_mask.rs b/src/bit_mask.rs index 5ce574007bc..ad6facfb199 100644 --- a/src/bit_mask.rs +++ b/src/bit_mask.rs @@ -12,23 +12,23 @@ declare_lint! { pub BAD_BIT_MASK, Deny, "Deny the use of incompatible bit masks in comparisons, e.g. \ - '(a & 1) == 2'" + '(a & 1) == 2'" } declare_lint! { - pub INEFFECTIVE_BIT_MASK, - Warn, - "Warn on the use of an ineffective bit mask in comparisons, e.g. \ - '(a & 1) > 2'" + pub INEFFECTIVE_BIT_MASK, + Warn, + "Warn on the use of an ineffective bit mask in comparisons, e.g. \ + '(a & 1) > 2'" } -/// Checks for incompatible bit masks in comparisons, e.g. `x & 1 == 2`. +/// Checks for incompatible bit masks in comparisons, e.g. `x & 1 == 2`. /// This cannot work because the bit that makes up the value two was /// zeroed out by the bit-and with 1. So the formula for detecting if an -/// expression of the type `_ m c` (where `` -/// is one of {`&`, '|'} and `` is one of {`!=`, `>=`, `>` , +/// expression of the type `_ m c` (where `` +/// is one of {`&`, '|'} and `` is one of {`!=`, `>=`, `>` , /// `!=`, `>=`, `>`}) can be determined from the following table: -/// +/// /// |Comparison |Bit-Op|Example |is always|Formula | /// |------------|------|------------|---------|----------------------| /// |`==` or `!=`| `&` |`x & 2 == 3`|`false` |`c & m != c` | @@ -37,7 +37,7 @@ declare_lint! { /// |`==` or `!=`| `|` |`x | 1 == 0`|`false` |`c | m != c` | /// |`<` or `>=`| `|` |`x | 1 < 1` |`false` |`m >= c` | /// |`<=` or `>` | `|` |`x | 1 > 0` |`true` |`m > c` | -/// +/// /// This lint is **deny** by default /// /// There is also a lint that warns on ineffective masks that is *warn* @@ -49,140 +49,140 @@ impl LintPass for BitMask { fn get_lints(&self) -> LintArray { lint_array!(BAD_BIT_MASK, INEFFECTIVE_BIT_MASK) } - + fn check_expr(&mut self, cx: &Context, e: &Expr) { if let ExprBinary(ref cmp, ref left, ref right) = e.node { - if is_comparison_binop(cmp.node) { - fetch_int_literal(cx, right).map_or_else(|| - fetch_int_literal(cx, left).map_or((), |cmp_val| - check_compare(cx, right, invert_cmp(cmp.node), - cmp_val, &e.span)), - |cmp_opt| check_compare(cx, left, cmp.node, cmp_opt, - &e.span)) - } - } + if is_comparison_binop(cmp.node) { + fetch_int_literal(cx, right).map_or_else(|| + fetch_int_literal(cx, left).map_or((), |cmp_val| + check_compare(cx, right, invert_cmp(cmp.node), + cmp_val, &e.span)), + |cmp_opt| check_compare(cx, left, cmp.node, cmp_opt, + &e.span)) + } + } } } fn invert_cmp(cmp : BinOp_) -> BinOp_ { - match cmp { - BiEq => BiEq, - BiNe => BiNe, - BiLt => BiGt, - BiGt => BiLt, - BiLe => BiGe, - BiGe => BiLe, - _ => BiOr // Dummy - } + match cmp { + BiEq => BiEq, + BiNe => BiNe, + BiLt => BiGt, + BiGt => BiLt, + BiLe => BiGe, + BiGe => BiLe, + _ => BiOr // Dummy + } } fn check_compare(cx: &Context, bit_op: &Expr, cmp_op: BinOp_, cmp_value: u64, span: &Span) { - match &bit_op.node { - &ExprParen(ref subexp) => check_compare(cx, subexp, cmp_op, cmp_value, span), - &ExprBinary(ref op, ref left, ref right) => { - if op.node != BiBitAnd && op.node != BiBitOr { return; } - fetch_int_literal(cx, right).or_else(|| fetch_int_literal( - cx, left)).map_or((), |mask| check_bit_mask(cx, op.node, - cmp_op, mask, cmp_value, span)) - }, - _ => () - } + match &bit_op.node { + &ExprParen(ref subexp) => check_compare(cx, subexp, cmp_op, cmp_value, span), + &ExprBinary(ref op, ref left, ref right) => { + if op.node != BiBitAnd && op.node != BiBitOr { return; } + fetch_int_literal(cx, right).or_else(|| fetch_int_literal( + cx, left)).map_or((), |mask| check_bit_mask(cx, op.node, + cmp_op, mask, cmp_value, span)) + }, + _ => () + } } -fn check_bit_mask(cx: &Context, bit_op: BinOp_, cmp_op: BinOp_, - mask_value: u64, cmp_value: u64, span: &Span) { - match cmp_op { - BiEq | BiNe => match bit_op { - BiBitAnd => if mask_value & cmp_value != mask_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, - &format!("&-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, - &format!("&-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 { - if mask_value < cmp_value { - span_lint(cx, INEFFECTIVE_BIT_MASK, *span, &format!( - "ineffective bit mask: x | {} compared to {} is the same as x compared directly", - 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, - &format!("&-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 { - if mask_value < cmp_value { - span_lint(cx, INEFFECTIVE_BIT_MASK, *span, &format!( - "ineffective bit mask: x | {} compared to {} is the same as x compared directly", - mask_value, cmp_value)); - } - }, - _ => () - }, - _ => () - } +fn check_bit_mask(cx: &Context, bit_op: BinOp_, cmp_op: BinOp_, + mask_value: u64, cmp_value: u64, span: &Span) { + match cmp_op { + BiEq | BiNe => match bit_op { + BiBitAnd => if mask_value & cmp_value != mask_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, + &format!("&-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, + &format!("&-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 { + if mask_value < cmp_value { + span_lint(cx, INEFFECTIVE_BIT_MASK, *span, &format!( + "ineffective bit mask: x | {} compared to {} is the same as x compared directly", + 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, + &format!("&-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 { + if mask_value < cmp_value { + span_lint(cx, INEFFECTIVE_BIT_MASK, *span, &format!( + "ineffective bit mask: x | {} compared to {} is the same as x compared directly", + mask_value, cmp_value)); + } + }, + _ => () + }, + _ => () + } } fn fetch_int_literal(cx: &Context, lit : &Expr) -> Option { - match &lit.node { - &ExprLit(ref lit_ptr) => { - if let &LitInt(value, _) = &lit_ptr.node { - Option::Some(value) //TODO: Handle sign - } else { Option::None } - }, - &ExprPath(_, _) => { - // Important to let the borrow expire before the const lookup to avoid double - // borrowing. - let def_map = cx.tcx.def_map.borrow(); - match def_map.get(&lit.id) { - Some(&PathResolution { base_def: DefConst(def_id), ..}) => Some(def_id), - _ => None - } + match &lit.node { + &ExprLit(ref lit_ptr) => { + if let &LitInt(value, _) = &lit_ptr.node { + Option::Some(value) //TODO: Handle sign + } else { Option::None } + }, + &ExprPath(_, _) => { + // Important to let the borrow expire before the const lookup to avoid double + // borrowing. + let def_map = cx.tcx.def_map.borrow(); + match def_map.get(&lit.id) { + Some(&PathResolution { base_def: DefConst(def_id), ..}) => Some(def_id), + _ => None } - .and_then(|def_id| lookup_const_by_id(cx.tcx, def_id, Option::None)) - .and_then(|l| fetch_int_literal(cx, l)), - _ => Option::None - } + } + .and_then(|def_id| lookup_const_by_id(cx.tcx, def_id, Option::None)) + .and_then(|l| fetch_int_literal(cx, l)), + _ => Option::None + } } diff --git a/src/collapsible_if.rs b/src/collapsible_if.rs index dc2d3852237..eae3222945c 100644 --- a/src/collapsible_if.rs +++ b/src/collapsible_if.rs @@ -34,24 +34,24 @@ impl LintPass for CollapsibleIf { fn get_lints(&self) -> LintArray { lint_array!(COLLAPSIBLE_IF) } - - fn check_expr(&mut self, cx: &Context, expr: &Expr) { - cx.sess().codemap().with_expn_info(expr.span.expn_id, - |info| check_expr_expd(cx, expr, info)) - } + + fn check_expr(&mut self, cx: &Context, expr: &Expr) { + cx.sess().codemap().with_expn_info(expr.span.expn_id, + |info| check_expr_expd(cx, expr, info)) + } } fn check_expr_expd(cx: &Context, e: &Expr, info: Option<&ExpnInfo>) { - if in_macro(cx, info) { return; } - - if let ExprIf(ref check, ref then, None) = e.node { - if let Some(&Expr{ node: ExprIf(ref check_inner, _, None), ..}) = - single_stmt_of_block(then) { - span_lint(cx, COLLAPSIBLE_IF, e.span, &format!( - "This if statement can be collapsed. Try: if {} && {}\n{:?}", - check_to_string(check), check_to_string(check_inner), e)); - } - } + if in_macro(cx, info) { return; } + + if let ExprIf(ref check, ref then, None) = e.node { + if let Some(&Expr{ node: ExprIf(ref check_inner, _, None), ..}) = + single_stmt_of_block(then) { + span_lint(cx, COLLAPSIBLE_IF, e.span, &format!( + "This if statement can be collapsed. Try: if {} && {}\n{:?}", + check_to_string(check), check_to_string(check_inner), e)); + } + } } fn requires_brackets(e: &Expr) -> bool { diff --git a/src/eq_op.rs b/src/eq_op.rs index 1000d310e39..6ad0e0658df 100644 --- a/src/eq_op.rs +++ b/src/eq_op.rs @@ -18,12 +18,12 @@ impl LintPass for EqOp { fn get_lints(&self) -> LintArray { lint_array!(EQ_OP) } - + fn check_expr(&mut self, cx: &Context, e: &Expr) { if let ExprBinary(ref op, ref left, ref right) = e.node { if is_cmp_or_bit(op) && is_exp_equal(left, right) { span_lint(cx, EQ_OP, e.span, &format!( - "equal expressions as operands to {}", + "equal expressions as operands to {}", ast_util::binop_to_string(op.node))); } } @@ -32,36 +32,36 @@ impl LintPass for EqOp { pub fn is_exp_equal(left : &Expr, right : &Expr) -> bool { match (&left.node, &right.node) { - (&ExprBinary(ref lop, ref ll, ref lr), - &ExprBinary(ref rop, ref rl, ref rr)) => - lop.node == rop.node && + (&ExprBinary(ref lop, ref ll, ref lr), + &ExprBinary(ref rop, ref rl, ref rr)) => + lop.node == rop.node && is_exp_equal(ll, rl) && is_exp_equal(lr, rr), - (&ExprBox(ref lpl, ref lbox), &ExprBox(ref rpl, ref rbox)) => - both(lpl, rpl, |l, r| is_exp_equal(l, r)) && + (&ExprBox(ref lpl, ref lbox), &ExprBox(ref rpl, ref rbox)) => + both(lpl, rpl, |l, r| is_exp_equal(l, r)) && is_exp_equal(lbox, rbox), - (&ExprCall(ref lcallee, ref largs), - &ExprCall(ref rcallee, ref rargs)) => is_exp_equal(lcallee, + (&ExprCall(ref lcallee, ref largs), + &ExprCall(ref rcallee, ref rargs)) => is_exp_equal(lcallee, rcallee) && is_exps_equal(largs, rargs), - (&ExprCast(ref lc, ref lty), &ExprCast(ref rc, ref rty)) => + (&ExprCast(ref lc, ref lty), &ExprCast(ref rc, ref rty)) => is_ty_equal(lty, rty) && is_exp_equal(lc, rc), - (&ExprField(ref lfexp, ref lfident), - &ExprField(ref rfexp, ref rfident)) => + (&ExprField(ref lfexp, ref lfident), + &ExprField(ref rfexp, ref rfident)) => lfident.node == rfident.node && is_exp_equal(lfexp, rfexp), (&ExprLit(ref l), &ExprLit(ref r)) => l.node == r.node, - (&ExprMethodCall(ref lident, ref lcty, ref lmargs), - &ExprMethodCall(ref rident, ref rcty, ref rmargs)) => - lident.node == rident.node && is_tys_equal(lcty, rcty) && + (&ExprMethodCall(ref lident, ref lcty, ref lmargs), + &ExprMethodCall(ref rident, ref rcty, ref rmargs)) => + lident.node == rident.node && is_tys_equal(lcty, rcty) && is_exps_equal(lmargs, rmargs), (&ExprParen(ref lparen), _) => is_exp_equal(lparen, right), (_, &ExprParen(ref rparen)) => is_exp_equal(left, rparen), - (&ExprPath(ref lqself, ref lsubpath), - &ExprPath(ref rqself, ref rsubpath)) => - both(lqself, rqself, |l, r| is_qself_equal(l, r)) && - is_path_equal(lsubpath, rsubpath), - (&ExprTup(ref ltup), &ExprTup(ref rtup)) => + (&ExprPath(ref lqself, ref lsubpath), + &ExprPath(ref rqself, ref rsubpath)) => + both(lqself, rqself, |l, r| is_qself_equal(l, r)) && + is_path_equal(lsubpath, rsubpath), + (&ExprTup(ref ltup), &ExprTup(ref rtup)) => is_exps_equal(ltup, rtup), - (&ExprUnary(lunop, ref l), &ExprUnary(runop, ref r)) => - lunop == runop && is_exp_equal(l, r), + (&ExprUnary(lunop, ref l), &ExprUnary(runop, ref r)) => + lunop == runop && is_exp_equal(l, r), (&ExprVec(ref l), &ExprVec(ref r)) => is_exps_equal(l, r), _ => false } @@ -74,7 +74,7 @@ fn is_exps_equal(left : &[P], right : &[P]) -> bool { fn is_path_equal(left : &Path, right : &Path) -> bool { // The == of idents doesn't work with different contexts, // we have to be explicit about hygiene - left.global == right.global && over(&left.segments, &right.segments, + left.global == right.global && over(&left.segments, &right.segments, |l, r| l.identifier.name == r.identifier.name && l.identifier.ctxt == r.identifier.ctxt && l.parameters == r.parameters) @@ -87,23 +87,23 @@ fn is_qself_equal(left : &QSelf, right : &QSelf) -> bool { fn is_ty_equal(left : &Ty, right : &Ty) -> bool { match (&left.node, &right.node) { (&TyVec(ref lvec), &TyVec(ref rvec)) => is_ty_equal(lvec, rvec), - (&TyFixedLengthVec(ref lfvty, ref lfvexp), - &TyFixedLengthVec(ref rfvty, ref rfvexp)) => + (&TyFixedLengthVec(ref lfvty, ref lfvexp), + &TyFixedLengthVec(ref rfvty, ref rfvexp)) => is_ty_equal(lfvty, rfvty) && is_exp_equal(lfvexp, rfvexp), (&TyPtr(ref lmut), &TyPtr(ref rmut)) => is_mut_ty_equal(lmut, rmut), - (&TyRptr(ref ltime, ref lrmut), &TyRptr(ref rtime, ref rrmut)) => - both(ltime, rtime, is_lifetime_equal) && + (&TyRptr(ref ltime, ref lrmut), &TyRptr(ref rtime, ref rrmut)) => + both(ltime, rtime, is_lifetime_equal) && is_mut_ty_equal(lrmut, rrmut), - (&TyBareFn(ref lbare), &TyBareFn(ref rbare)) => + (&TyBareFn(ref lbare), &TyBareFn(ref rbare)) => is_bare_fn_ty_equal(lbare, rbare), (&TyTup(ref ltup), &TyTup(ref rtup)) => is_tys_equal(ltup, rtup), - (&TyPath(ref lq, ref lpath), &TyPath(ref rq, ref rpath)) => + (&TyPath(ref lq, ref lpath), &TyPath(ref rq, ref rpath)) => both(lq, rq, is_qself_equal) && is_path_equal(lpath, rpath), - (&TyObjectSum(ref lsumty, ref lobounds), - &TyObjectSum(ref rsumty, ref robounds)) => - is_ty_equal(lsumty, rsumty) && + (&TyObjectSum(ref lsumty, ref lobounds), + &TyObjectSum(ref rsumty, ref robounds)) => + is_ty_equal(lsumty, rsumty) && is_param_bounds_equal(lobounds, robounds), - (&TyPolyTraitRef(ref ltbounds), &TyPolyTraitRef(ref rtbounds)) => + (&TyPolyTraitRef(ref ltbounds), &TyPolyTraitRef(ref rtbounds)) => is_param_bounds_equal(ltbounds, rtbounds), (&TyParen(ref lty), &TyParen(ref rty)) => is_ty_equal(lty, rty), (&TyTypeof(ref lof), &TyTypeof(ref rof)) => is_exp_equal(lof, rof), @@ -112,13 +112,13 @@ fn is_ty_equal(left : &Ty, right : &Ty) -> bool { } } -fn is_param_bound_equal(left : &TyParamBound, right : &TyParamBound) +fn is_param_bound_equal(left : &TyParamBound, right : &TyParamBound) -> bool { match(left, right) { - (&TraitTyParamBound(ref lpoly, ref lmod), - &TraitTyParamBound(ref rpoly, ref rmod)) => + (&TraitTyParamBound(ref lpoly, ref lmod), + &TraitTyParamBound(ref rpoly, ref rmod)) => lmod == rmod && is_poly_traitref_equal(lpoly, rpoly), - (&RegionTyParamBound(ref ltime), &RegionTyParamBound(ref rtime)) => + (&RegionTyParamBound(ref ltime), &RegionTyParamBound(ref rtime)) => is_lifetime_equal(ltime, rtime), _ => false } @@ -140,24 +140,24 @@ fn is_mut_ty_equal(left : &MutTy, right : &MutTy) -> bool { } fn is_bare_fn_ty_equal(left : &BareFnTy, right : &BareFnTy) -> bool { - left.unsafety == right.unsafety && left.abi == right.abi && - is_lifetimedefs_equal(&left.lifetimes, &right.lifetimes) && + left.unsafety == right.unsafety && left.abi == right.abi && + is_lifetimedefs_equal(&left.lifetimes, &right.lifetimes) && is_fndecl_equal(&left.decl, &right.decl) -} +} fn is_fndecl_equal(left : &P, right : &P) -> bool { - left.variadic == right.variadic && - is_args_equal(&left.inputs, &right.inputs) && + left.variadic == right.variadic && + is_args_equal(&left.inputs, &right.inputs) && is_fnret_ty_equal(&left.output, &right.output) } -fn is_fnret_ty_equal(left : &FunctionRetTy, right : &FunctionRetTy) +fn is_fnret_ty_equal(left : &FunctionRetTy, right : &FunctionRetTy) -> bool { match (left, right) { - (&NoReturn(_), &NoReturn(_)) | + (&NoReturn(_), &NoReturn(_)) | (&DefaultReturn(_), &DefaultReturn(_)) => true, (&Return(ref lty), &Return(ref rty)) => is_ty_equal(lty, rty), - _ => false + _ => false } } @@ -172,49 +172,49 @@ fn is_args_equal(left : &[Arg], right : &[Arg]) -> bool { fn is_pat_equal(left : &Pat, right : &Pat) -> bool { match(&left.node, &right.node) { (&PatWild(lwild), &PatWild(rwild)) => lwild == rwild, - (&PatIdent(ref lmode, ref lident, Option::None), + (&PatIdent(ref lmode, ref lident, Option::None), &PatIdent(ref rmode, ref rident, Option::None)) => lmode == rmode && is_ident_equal(&lident.node, &rident.node), - (&PatIdent(ref lmode, ref lident, Option::Some(ref lpat)), + (&PatIdent(ref lmode, ref lident, Option::Some(ref lpat)), &PatIdent(ref rmode, ref rident, Option::Some(ref rpat))) => - lmode == rmode && is_ident_equal(&lident.node, &rident.node) && + lmode == rmode && is_ident_equal(&lident.node, &rident.node) && is_pat_equal(lpat, rpat), - (&PatEnum(ref lpath, ref lenum), &PatEnum(ref rpath, ref renum)) => - is_path_equal(lpath, rpath) && both(lenum, renum, |l, r| + (&PatEnum(ref lpath, ref lenum), &PatEnum(ref rpath, ref renum)) => + is_path_equal(lpath, rpath) && both(lenum, renum, |l, r| is_pats_equal(l, r)), - (&PatStruct(ref lpath, ref lfieldpat, lbool), + (&PatStruct(ref lpath, ref lfieldpat, lbool), &PatStruct(ref rpath, ref rfieldpat, rbool)) => - lbool == rbool && is_path_equal(lpath, rpath) && + lbool == rbool && is_path_equal(lpath, rpath) && is_spanned_fieldpats_equal(lfieldpat, rfieldpat), - (&PatTup(ref ltup), &PatTup(ref rtup)) => is_pats_equal(ltup, rtup), - (&PatBox(ref lboxed), &PatBox(ref rboxed)) => + (&PatTup(ref ltup), &PatTup(ref rtup)) => is_pats_equal(ltup, rtup), + (&PatBox(ref lboxed), &PatBox(ref rboxed)) => is_pat_equal(lboxed, rboxed), - (&PatRegion(ref lpat, ref lmut), &PatRegion(ref rpat, ref rmut)) => + (&PatRegion(ref lpat, ref lmut), &PatRegion(ref rpat, ref rmut)) => is_pat_equal(lpat, rpat) && lmut == rmut, (&PatLit(ref llit), &PatLit(ref rlit)) => is_exp_equal(llit, rlit), (&PatRange(ref lfrom, ref lto), &PatRange(ref rfrom, ref rto)) => is_exp_equal(lfrom, rfrom) && is_exp_equal(lto, rto), - (&PatVec(ref lfirst, Option::None, ref llast), + (&PatVec(ref lfirst, Option::None, ref llast), &PatVec(ref rfirst, Option::None, ref rlast)) => is_pats_equal(lfirst, rfirst) && is_pats_equal(llast, rlast), - (&PatVec(ref lfirst, Option::Some(ref lpat), ref llast), + (&PatVec(ref lfirst, Option::Some(ref lpat), ref llast), &PatVec(ref rfirst, Option::Some(ref rpat), ref rlast)) => - is_pats_equal(lfirst, rfirst) && is_pat_equal(lpat, rpat) && + is_pats_equal(lfirst, rfirst) && is_pat_equal(lpat, rpat) && is_pats_equal(llast, rlast), // I don't match macros for now, the code is slow enough as is ;-) _ => false } } -fn is_spanned_fieldpats_equal(left : &[code::Spanned], +fn is_spanned_fieldpats_equal(left : &[code::Spanned], right : &[code::Spanned]) -> bool { over(left, right, |l, r| is_fieldpat_equal(&l.node, &r.node)) } fn is_fieldpat_equal(left : &FieldPat, right : &FieldPat) -> bool { - left.is_shorthand == right.is_shorthand && - is_ident_equal(&left.ident, &right.ident) && - is_pat_equal(&left.pat, &right.pat) + left.is_shorthand == right.is_shorthand && + is_ident_equal(&left.ident, &right.ident) && + is_pat_equal(&left.pat, &right.pat) } fn is_ident_equal(left : &Ident, right : &Ident) -> bool { @@ -227,11 +227,11 @@ fn is_pats_equal(left : &[P], right : &[P]) -> bool { fn is_lifetimedef_equal(left : &LifetimeDef, right : &LifetimeDef) -> bool { - is_lifetime_equal(&left.lifetime, &right.lifetime) && + is_lifetime_equal(&left.lifetime, &right.lifetime) && over(&left.bounds, &right.bounds, is_lifetime_equal) } -fn is_lifetimedefs_equal(left : &[LifetimeDef], right : &[LifetimeDef]) +fn is_lifetimedefs_equal(left : &[LifetimeDef], right : &[LifetimeDef]) -> bool { over(left, right, is_lifetimedef_equal) } @@ -244,13 +244,13 @@ fn is_tys_equal(left : &[P], right : &[P]) -> bool { over(left, right, |l, r| is_ty_equal(l, r)) } -fn over(left: &[X], right: &[X], mut eq_fn: F) -> bool +fn over(left: &[X], right: &[X], mut eq_fn: F) -> bool where F: FnMut(&X, &X) -> bool { - left.len() == right.len() && left.iter().zip(right).all(|(x, y)| + left.len() == right.len() && left.iter().zip(right).all(|(x, y)| eq_fn(x, y)) } -fn both(l: &Option, r: &Option, mut eq_fn : F) -> bool +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))) @@ -258,7 +258,7 @@ fn both(l: &Option, r: &Option, mut eq_fn : F) -> bool fn is_cmp_or_bit(op : &BinOp) -> bool { match op.node { - BiEq | BiLt | BiLe | BiGt | BiGe | BiNe | BiAnd | BiOr | + BiEq | BiLt | BiLe | BiGt | BiGe | BiNe | BiAnd | BiOr | BiBitXor | BiBitAnd | BiBitOr => true, _ => false } diff --git a/src/eta_reduction.rs b/src/eta_reduction.rs index 18011c61831..6948c1b22ab 100644 --- a/src/eta_reduction.rs +++ b/src/eta_reduction.rs @@ -58,4 +58,3 @@ impl LintPass for EtaPass { } } } - diff --git a/src/identity_op.rs b/src/identity_op.rs index b3fb3e05447..56d01c52b1d 100644 --- a/src/identity_op.rs +++ b/src/identity_op.rs @@ -11,7 +11,7 @@ use utils::{span_lint, snippet}; declare_lint! { pub IDENTITY_OP, Warn, "Warn on identity operations, e.g. '_ + 0'"} - + #[derive(Copy,Clone)] pub struct IdentityOp; @@ -27,7 +27,7 @@ impl LintPass for IdentityOp { check(cx, left, 0, e.span, right.span); check(cx, right, 0, e.span, left.span); }, - BiShl | BiShr | BiSub => + BiShl | BiShr | BiSub => check(cx, right, 0, e.span, left.span), BiMul => { check(cx, left, 1, e.span, right.span); @@ -49,14 +49,14 @@ impl LintPass for IdentityOp { fn check(cx: &Context, e: &Expr, m: i8, span: Span, arg: Span) { if have_lit(cx, e, m) { span_lint(cx, IDENTITY_OP, span, &format!( - "The operation is ineffective. Consider reducing it to '{}'", + "The operation is ineffective. Consider reducing it to '{}'", snippet(cx, arg, ".."))); } } fn have_lit(cx: &Context, e : &Expr, m: i8) -> bool { match &e.node { - &ExprUnary(UnNeg, ref litexp) => have_lit(cx, litexp, -m), + &ExprUnary(UnNeg, ref litexp) => have_lit(cx, litexp, -m), &ExprLit(ref lit) => { match (&lit.node, m) { (&LitInt(0, _), 0) => true, @@ -68,9 +68,9 @@ fn have_lit(cx: &Context, e : &Expr, m: i8) -> bool { } }, &ExprParen(ref p) => have_lit(cx, p, m), - &ExprPath(_, _) => { + &ExprPath(_, _) => { match cx.tcx.def_map.borrow().get(&e.id) { - Some(&PathResolution { base_def: DefConst(id), ..}) => + Some(&PathResolution { base_def: DefConst(id), ..}) => lookup_const_by_id(cx.tcx, id, Option::None) .map_or(false, |l| have_lit(cx, l, m)), _ => false diff --git a/src/len_zero.rs b/src/len_zero.rs index 37683bbfa53..0877fa95238 100644 --- a/src/len_zero.rs +++ b/src/len_zero.rs @@ -22,130 +22,130 @@ declare_lint!(pub LEN_WITHOUT_IS_EMPTY, Warn, pub struct LenZero; impl LintPass for LenZero { - fn get_lints(&self) -> LintArray { + fn get_lints(&self) -> LintArray { lint_array!(LEN_ZERO, LEN_WITHOUT_IS_EMPTY) - } - - fn check_item(&mut self, cx: &Context, item: &Item) { - match &item.node { - &ItemTrait(_, _, _, ref trait_items) => - check_trait_items(cx, item, trait_items), - &ItemImpl(_, _, _, None, _, ref impl_items) => // only non-trait - check_impl_items(cx, item, impl_items), - _ => () - } - } - - fn check_expr(&mut self, cx: &Context, expr: &Expr) { - if let &ExprBinary(Spanned{node: cmp, ..}, ref left, ref right) = - &expr.node { - match cmp { - BiEq => check_cmp(cx, expr.span, left, right, ""), - BiGt | BiNe => check_cmp(cx, expr.span, left, right, "!"), - _ => () - } - } - } + } + + fn check_item(&mut self, cx: &Context, item: &Item) { + match &item.node { + &ItemTrait(_, _, _, ref trait_items) => + check_trait_items(cx, item, trait_items), + &ItemImpl(_, _, _, None, _, ref impl_items) => // only non-trait + check_impl_items(cx, item, impl_items), + _ => () + } + } + + fn check_expr(&mut self, cx: &Context, expr: &Expr) { + if let &ExprBinary(Spanned{node: cmp, ..}, ref left, ref right) = + &expr.node { + match cmp { + BiEq => check_cmp(cx, expr.span, left, right, ""), + BiGt | BiNe => check_cmp(cx, expr.span, left, right, "!"), + _ => () + } + } + } } fn check_trait_items(cx: &Context, item: &Item, trait_items: &[P]) { - fn is_named_self(item: &TraitItem, name: &str) -> bool { - item.ident.name == name && if let MethodTraitItem(ref sig, _) = - item.node { is_self_sig(sig) } else { false } - } + fn is_named_self(item: &TraitItem, name: &str) -> bool { + item.ident.name == name && if let MethodTraitItem(ref sig, _) = + item.node { is_self_sig(sig) } else { false } + } - if !trait_items.iter().any(|i| is_named_self(i, "is_empty")) { - //span_lint(cx, LEN_WITHOUT_IS_EMPTY, item.span, &format!("trait {}", item.ident.as_str())); - for i in trait_items { - if is_named_self(i, "len") { - span_lint(cx, LEN_WITHOUT_IS_EMPTY, i.span, - &format!("Trait '{}' has a '.len(_: &Self)' method, but no \ - '.is_empty(_: &Self)' method. Consider adding one.", - item.ident.name)); - } - }; - } + if !trait_items.iter().any(|i| is_named_self(i, "is_empty")) { + //span_lint(cx, LEN_WITHOUT_IS_EMPTY, item.span, &format!("trait {}", item.ident.as_str())); + for i in trait_items { + if is_named_self(i, "len") { + span_lint(cx, LEN_WITHOUT_IS_EMPTY, i.span, + &format!("Trait '{}' has a '.len(_: &Self)' method, but no \ + '.is_empty(_: &Self)' method. Consider adding one.", + item.ident.name)); + } + }; + } } fn check_impl_items(cx: &Context, item: &Item, impl_items: &[P]) { - fn is_named_self(item: &ImplItem, name: &str) -> bool { - item.ident.name == name && if let MethodImplItem(ref sig, _) = - item.node { is_self_sig(sig) } else { false } - } + fn is_named_self(item: &ImplItem, name: &str) -> bool { + item.ident.name == name && if let MethodImplItem(ref sig, _) = + item.node { is_self_sig(sig) } else { false } + } - if !impl_items.iter().any(|i| is_named_self(i, "is_empty")) { - for i in impl_items { - if is_named_self(i, "len") { - let s = i.span; - span_lint(cx, LEN_WITHOUT_IS_EMPTY, - Span{ lo: s.lo, hi: s.lo, expn_id: s.expn_id }, - &format!("Item '{}' has a '.len(_: &Self)' method, but no \ - '.is_empty(_: &Self)' method. Consider adding one.", - item.ident.name)); - return; - } - } - } + if !impl_items.iter().any(|i| is_named_self(i, "is_empty")) { + for i in impl_items { + if is_named_self(i, "len") { + let s = i.span; + span_lint(cx, LEN_WITHOUT_IS_EMPTY, + Span{ lo: s.lo, hi: s.lo, expn_id: s.expn_id }, + &format!("Item '{}' has a '.len(_: &Self)' method, but no \ + '.is_empty(_: &Self)' method. Consider adding one.", + item.ident.name)); + return; + } + } + } } fn is_self_sig(sig: &MethodSig) -> bool { - if let SelfStatic = sig.explicit_self.node { - false } else { sig.decl.inputs.len() == 1 } + if let SelfStatic = sig.explicit_self.node { + false } else { sig.decl.inputs.len() == 1 } } fn check_cmp(cx: &Context, span: Span, left: &Expr, right: &Expr, empty: &str) { - match (&left.node, &right.node) { - (&ExprLit(ref lit), &ExprMethodCall(ref method, _, ref args)) => - check_len_zero(cx, span, method, args, lit, empty), - (&ExprMethodCall(ref method, _, ref args), &ExprLit(ref lit)) => - check_len_zero(cx, span, method, args, lit, empty), - _ => () - } + match (&left.node, &right.node) { + (&ExprLit(ref lit), &ExprMethodCall(ref method, _, ref args)) => + check_len_zero(cx, span, method, args, lit, empty), + (&ExprMethodCall(ref method, _, ref args), &ExprLit(ref lit)) => + check_len_zero(cx, span, method, args, lit, empty), + _ => () + } } -fn check_len_zero(cx: &Context, span: Span, method: &SpannedIdent, - args: &[P], lit: &Lit, empty: &str) { - if let &Spanned{node: LitInt(0, _), ..} = lit { - if method.node.name == "len" && args.len() == 1 && - has_is_empty(cx, &*args[0]) { - span_lint(cx, LEN_ZERO, span, &format!( - "Consider replacing the len comparison with '{}_.is_empty()'", - empty)) - } - } +fn check_len_zero(cx: &Context, span: Span, method: &SpannedIdent, + args: &[P], lit: &Lit, empty: &str) { + if let &Spanned{node: LitInt(0, _), ..} = lit { + if method.node.name == "len" && args.len() == 1 && + has_is_empty(cx, &*args[0]) { + span_lint(cx, LEN_ZERO, span, &format!( + "Consider replacing the len comparison with '{}_.is_empty()'", + empty)) + } + } } /// check if this type has an is_empty method fn has_is_empty(cx: &Context, expr: &Expr) -> bool { - /// get a ImplOrTraitItem and return true if it matches is_empty(self) - fn is_is_empty(cx: &Context, id: &ImplOrTraitItemId) -> bool { - if let &MethodTraitItemId(def_id) = id { - if let ty::MethodTraitItem(ref method) = - cx.tcx.impl_or_trait_item(def_id) { - method.name.as_str() == "is_empty" - && method.fty.sig.skip_binder().inputs.len() == 1 - } else { false } - } else { false } - } - - /// check the inherent impl's items for an is_empty(self) method - fn has_is_empty_impl(cx: &Context, id: &DefId) -> bool { - let impl_items = cx.tcx.impl_items.borrow(); - cx.tcx.inherent_impls.borrow().get(id).map_or(false, - |ids| ids.iter().any(|iid| impl_items.get(iid).map_or(false, - |iids| iids.iter().any(|i| is_is_empty(cx, i))))) - } - - let ty = &walk_ty(&cx.tcx.expr_ty(expr)); - match ty.sty { - ty::TyTrait(_) => cx.tcx.trait_item_def_ids.borrow().get( - &ty.ty_to_def_id().expect("trait impl not found")).map_or(false, - |ids| ids.iter().any(|i| is_is_empty(cx, i))), - ty::TyProjection(_) => ty.ty_to_def_id().map_or(false, - |id| has_is_empty_impl(cx, &id)), - ty::TyEnum(ref id, _) | ty::TyStruct(ref id, _) => - has_is_empty_impl(cx, &id.did), - ty::TyArray(..) => true, - _ => false, - } + /// get a ImplOrTraitItem and return true if it matches is_empty(self) + fn is_is_empty(cx: &Context, id: &ImplOrTraitItemId) -> bool { + if let &MethodTraitItemId(def_id) = id { + if let ty::MethodTraitItem(ref method) = + cx.tcx.impl_or_trait_item(def_id) { + method.name.as_str() == "is_empty" + && method.fty.sig.skip_binder().inputs.len() == 1 + } else { false } + } else { false } + } + + /// check the inherent impl's items for an is_empty(self) method + fn has_is_empty_impl(cx: &Context, id: &DefId) -> bool { + let impl_items = cx.tcx.impl_items.borrow(); + cx.tcx.inherent_impls.borrow().get(id).map_or(false, + |ids| ids.iter().any(|iid| impl_items.get(iid).map_or(false, + |iids| iids.iter().any(|i| is_is_empty(cx, i))))) + } + + let ty = &walk_ty(&cx.tcx.expr_ty(expr)); + match ty.sty { + ty::TyTrait(_) => cx.tcx.trait_item_def_ids.borrow().get( + &ty.ty_to_def_id().expect("trait impl not found")).map_or(false, + |ids| ids.iter().any(|i| is_is_empty(cx, i))), + ty::TyProjection(_) => ty.ty_to_def_id().map_or(false, + |id| has_is_empty_impl(cx, &id)), + ty::TyEnum(ref id, _) | ty::TyStruct(ref id, _) => + has_is_empty_impl(cx, &id.did), + ty::TyArray(..) => true, + _ => false, + } } diff --git a/src/mut_mut.rs b/src/mut_mut.rs index 73e97ae31f4..16ea422f77f 100644 --- a/src/mut_mut.rs +++ b/src/mut_mut.rs @@ -12,50 +12,50 @@ declare_lint!(pub MUT_MUT, Warn, pub struct MutMut; impl LintPass for MutMut { - fn get_lints(&self) -> LintArray { + fn get_lints(&self) -> LintArray { lint_array!(MUT_MUT) - } - - fn check_expr(&mut self, cx: &Context, expr: &Expr) { - cx.sess().codemap().with_expn_info(expr.span.expn_id, - |info| check_expr_expd(cx, expr, info)) - } - - fn check_ty(&mut self, cx: &Context, ty: &Ty) { - unwrap_mut(ty).and_then(unwrap_mut).map_or((), |_| span_lint(cx, MUT_MUT, - ty.span, "Generally you want to avoid &mut &mut _ if possible.")) - } + } + + fn check_expr(&mut self, cx: &Context, expr: &Expr) { + cx.sess().codemap().with_expn_info(expr.span.expn_id, + |info| check_expr_expd(cx, expr, info)) + } + + fn check_ty(&mut self, cx: &Context, ty: &Ty) { + unwrap_mut(ty).and_then(unwrap_mut).map_or((), |_| span_lint(cx, MUT_MUT, + ty.span, "Generally you want to avoid &mut &mut _ if possible.")) + } } fn check_expr_expd(cx: &Context, expr: &Expr, info: Option<&ExpnInfo>) { - if in_macro(cx, info) { return; } + if in_macro(cx, info) { return; } - fn unwrap_addr(expr : &Expr) -> Option<&Expr> { - match expr.node { - ExprAddrOf(MutMutable, ref e) => Option::Some(e), - _ => Option::None - } - } - - unwrap_addr(expr).map_or((), |e| { - unwrap_addr(e).map(|_| { - span_lint(cx, MUT_MUT, expr.span, - "Generally you want to avoid &mut &mut _ if possible.") - }).unwrap_or_else(|| { - if let TyRef(_, TypeAndMut{ty: _, mutbl: MutMutable}) = - cx.tcx.expr_ty(e).sty { - span_lint(cx, MUT_MUT, expr.span, - "This expression mutably borrows a mutable reference. \ - Consider reborrowing") - } - }) - }) + fn unwrap_addr(expr : &Expr) -> Option<&Expr> { + match expr.node { + ExprAddrOf(MutMutable, ref e) => Option::Some(e), + _ => Option::None + } + } + + unwrap_addr(expr).map_or((), |e| { + unwrap_addr(e).map(|_| { + span_lint(cx, MUT_MUT, expr.span, + "Generally you want to avoid &mut &mut _ if possible.") + }).unwrap_or_else(|| { + if let TyRef(_, TypeAndMut{ty: _, mutbl: MutMutable}) = + cx.tcx.expr_ty(e).sty { + span_lint(cx, MUT_MUT, expr.span, + "This expression mutably borrows a mutable reference. \ + Consider reborrowing") + } + }) + }) } fn unwrap_mut(ty : &Ty) -> Option<&Ty> { - match ty.node { - TyPtr(MutTy{ ty: ref pty, mutbl: MutMutable }) => Option::Some(pty), - TyRptr(_, MutTy{ ty: ref pty, mutbl: MutMutable }) => Option::Some(pty), - _ => Option::None - } + match ty.node { + TyPtr(MutTy{ ty: ref pty, mutbl: MutMutable }) => Option::Some(pty), + TyRptr(_, MutTy{ ty: ref pty, mutbl: MutMutable }) => Option::Some(pty), + _ => Option::None + } } diff --git a/src/needless_bool.rs b/src/needless_bool.rs index 35d921e8fa1..3296bdeca87 100644 --- a/src/needless_bool.rs +++ b/src/needless_bool.rs @@ -25,38 +25,39 @@ impl LintPass for NeedlessBool { fn get_lints(&self) -> LintArray { lint_array!(NEEDLESS_BOOL) } - + fn check_expr(&mut self, cx: &Context, e: &Expr) { if let ExprIf(_, ref then_block, Option::Some(ref else_expr)) = e.node { - match (fetch_bool_block(then_block), fetch_bool_expr(else_expr)) { - (Option::Some(true), Option::Some(true)) => { - span_lint(cx, NEEDLESS_BOOL, e.span, - "your if-then-else expression will always return true"); }, - (Option::Some(true), Option::Some(false)) => { - span_lint(cx, NEEDLESS_BOOL, e.span, - "you can reduce your if-statement to its predicate"); }, - (Option::Some(false), Option::Some(true)) => { - span_lint(cx, NEEDLESS_BOOL, e.span, - "you can reduce your if-statement to '!' + your predicate"); }, - (Option::Some(false), Option::Some(false)) => { - span_lint(cx, NEEDLESS_BOOL, e.span, - "your if-then-else expression will always return false"); }, - _ => () - } - } + match (fetch_bool_block(then_block), fetch_bool_expr(else_expr)) { + (Option::Some(true), Option::Some(true)) => { + span_lint(cx, NEEDLESS_BOOL, e.span, + "your if-then-else expression will always return true"); }, + (Option::Some(true), Option::Some(false)) => { + span_lint(cx, NEEDLESS_BOOL, e.span, + "you can reduce your if-statement to its predicate"); }, + (Option::Some(false), Option::Some(true)) => { + span_lint(cx, NEEDLESS_BOOL, e.span, + "you can reduce your if-statement to '!' + your predicate"); }, + (Option::Some(false), Option::Some(false)) => { + span_lint(cx, NEEDLESS_BOOL, e.span, + "your if-then-else expression will always return false"); }, + _ => () + } + } } } fn fetch_bool_block(block: &Block) -> Option { - if block.stmts.is_empty() { - block.expr.as_ref().map(de_p).and_then(fetch_bool_expr) - } else { Option::None } + if block.stmts.is_empty() { + block.expr.as_ref().map(de_p).and_then(fetch_bool_expr) + } else { Option::None } } - + fn fetch_bool_expr(expr: &Expr) -> Option { - match &expr.node { - &ExprBlock(ref block) => fetch_bool_block(block), - &ExprLit(ref lit_ptr) => if let &LitBool(value) = &lit_ptr.node { Option::Some(value) } else { Option::None }, - _ => Option::None - } + match &expr.node { + &ExprBlock(ref block) => fetch_bool_block(block), + &ExprLit(ref lit_ptr) => if let &LitBool(value) = &lit_ptr.node { + Option::Some(value) } else { Option::None }, + _ => Option::None + } } diff --git a/src/ptr_arg.rs b/src/ptr_arg.rs index dad4e48c832..939277fe66c 100644 --- a/src/ptr_arg.rs +++ b/src/ptr_arg.rs @@ -26,44 +26,44 @@ impl LintPass for PtrArg { fn get_lints(&self) -> LintArray { lint_array!(PTR_ARG) } - + fn check_item(&mut self, cx: &Context, item: &Item) { - if let &ItemFn(ref decl, _, _, _, _, _) = &item.node { - check_fn(cx, decl); - } - } - - fn check_impl_item(&mut self, cx: &Context, item: &ImplItem) { - if let &MethodImplItem(ref sig, _) = &item.node { - check_fn(cx, &sig.decl); - } - } - - fn check_trait_item(&mut self, cx: &Context, item: &TraitItem) { - if let &MethodTraitItem(ref sig, _) = &item.node { - check_fn(cx, &sig.decl); - } - } + if let &ItemFn(ref decl, _, _, _, _, _) = &item.node { + check_fn(cx, decl); + } + } + + fn check_impl_item(&mut self, cx: &Context, item: &ImplItem) { + if let &MethodImplItem(ref sig, _) = &item.node { + check_fn(cx, &sig.decl); + } + } + + fn check_trait_item(&mut self, cx: &Context, item: &TraitItem) { + if let &MethodTraitItem(ref sig, _) = &item.node { + check_fn(cx, &sig.decl); + } + } } fn check_fn(cx: &Context, decl: &FnDecl) { - for arg in &decl.inputs { - match &arg.ty.node { - &TyPtr(ref p) | &TyRptr(_, ref p) => - check_ptr_subtype(cx, arg.ty.span, &p.ty), - _ => () - } - } + for arg in &decl.inputs { + match &arg.ty.node { + &TyPtr(ref p) | &TyRptr(_, ref p) => + check_ptr_subtype(cx, arg.ty.span, &p.ty), + _ => () + } + } } fn check_ptr_subtype(cx: &Context, span: Span, ty: &Ty) { - match_ty_unwrap(ty, &["Vec"]).map_or_else(|| match_ty_unwrap(ty, - &["String"]).map_or((), |_| { - span_lint(cx, PTR_ARG, span, - "Writing '&String' instead of '&str' involves a new Object \ - where a slices will do. Consider changing the type to &str") - }), |_| span_lint(cx, PTR_ARG, span, "Writing '&Vec<_>' instead of \ - '&[_]' involves one more reference and cannot be used with \ - non-vec-based slices. Consider changing the type to &[...]") - ) + match_ty_unwrap(ty, &["Vec"]).map_or_else(|| match_ty_unwrap(ty, + &["String"]).map_or((), |_| { + span_lint(cx, PTR_ARG, span, + "Writing '&String' instead of '&str' involves a new Object \ + where a slices will do. Consider changing the type to &str") + }), |_| span_lint(cx, PTR_ARG, span, + "Writing '&Vec<_>' instead of \ + '&[_]' involves one more reference and cannot be used with \ + non-vec-based slices. Consider changing the type to &[...]")) } diff --git a/src/strings.rs b/src/strings.rs index 511d123b58d..3384eed8da5 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -1,5 +1,5 @@ //! This LintPass catches both string addition and string addition + assignment -//! +//! //! Note that since we have two lints where one subsumes the other, we try to //! disable the subsumed lint unless it has a higher level @@ -25,11 +25,11 @@ impl LintPass for StringAdd { fn get_lints(&self) -> LintArray { lint_array!(STRING_ADD_ASSIGN) } - + fn check_expr(&mut self, cx: &Context, e: &Expr) { if let &ExprAssign(ref target, ref src) = &e.node { - if is_string(cx, target) && is_add(src, target) { - span_lint(cx, STRING_ADD_ASSIGN, e.span, + if is_string(cx, target) && is_add(src, target) { + span_lint(cx, STRING_ADD_ASSIGN, e.span, "You assign the result of adding something to this string. \ Consider using `String::push_str(..) instead.") } @@ -47,7 +47,7 @@ fn is_add(src: &Expr, target: &Expr) -> bool { match &src.node { &ExprBinary(Spanned{ node: BiAdd, .. }, ref left, _) => is_exp_equal(target, left), - &ExprBlock(ref block) => block.stmts.is_empty() && + &ExprBlock(ref block) => block.stmts.is_empty() && block.expr.as_ref().map_or(false, |expr| is_add(&*expr, target)), &ExprParen(ref expr) => is_add(&*expr, target), _ => false diff --git a/src/unicode.rs b/src/unicode.rs index 9b908c3f94f..1854d5be7ff 100644 --- a/src/unicode.rs +++ b/src/unicode.rs @@ -9,38 +9,38 @@ declare_lint!{ pub ZERO_WIDTH_SPACE, Deny, "Zero-width space is confusing" } pub struct Unicode; impl LintPass for Unicode { - fn get_lints(&self) -> LintArray { + fn get_lints(&self) -> LintArray { lint_array!(ZERO_WIDTH_SPACE) } - + fn check_expr(&mut self, cx: &Context, expr: &Expr) { - if let ExprLit(ref lit) = expr.node { - if let LitStr(ref string, _) = lit.node { - check_str(cx, string, lit.span) - } - } - } + if let ExprLit(ref lit) = expr.node { + if let LitStr(ref string, _) = lit.node { + check_str(cx, string, lit.span) + } + } + } } fn check_str(cx: &Context, string: &str, span: Span) { - let mut start: Option = None; - for (i, c) in string.char_indices() { - if c == '\u{200B}' { - if start.is_none() { start = Some(i); } - } else { - lint_zero_width(cx, span, start); - start = None; - } - } - lint_zero_width(cx, span, start); + let mut start: Option = None; + for (i, c) in string.char_indices() { + if c == '\u{200B}' { + if start.is_none() { start = Some(i); } + } else { + lint_zero_width(cx, span, start); + start = None; + } + } + lint_zero_width(cx, span, start); } fn lint_zero_width(cx: &Context, span: Span, start: Option) { - start.map(|index| { - span_lint(cx, ZERO_WIDTH_SPACE, Span { - lo: span.lo + BytePos(index as u32), - hi: span.lo + BytePos(index as u32), - expn_id: span.expn_id, - }, "Zero-width space detected. Consider using \\u{200B}") - }); + start.map(|index| { + span_lint(cx, ZERO_WIDTH_SPACE, Span { + lo: span.lo + BytePos(index as u32), + hi: span.lo + BytePos(index as u32), + expn_id: span.expn_id, + }, "Zero-width space detected. Consider using \\u{200B}") + }); } diff --git a/src/utils.rs b/src/utils.rs index a231171aee5..4f5763b1491 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -15,7 +15,7 @@ pub fn in_macro(cx: &Context, opt_info: Option<&ExpnInfo>) -> 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| + cx.sess().codemap().span_to_snippet(span).ok().map_or(true, |code| // macro doesn't start with "macro_rules" // = compiler plugin !code.starts_with("macro_rules") @@ -26,7 +26,7 @@ pub fn in_macro(cx: &Context, opt_info: Option<&ExpnInfo>) -> bool { /// invokes in_macro with the expansion info of the given span pub fn in_external_macro(cx: &Context, span: Span) -> bool { - cx.sess().codemap().with_expn_info(span.expn_id, + cx.sess().codemap().with_expn_info(span.expn_id, |info| in_macro(cx, info)) } @@ -57,7 +57,7 @@ pub fn get_parent_expr<'c>(cx: &'c Context, e: &Expr) -> Option<&'c Expr> { let node_id : NodeId = e.id; let parent_id : NodeId = map.get_parent_node(node_id); if node_id == parent_id { return None; } - map.find(parent_id).and_then(|node| + map.find(parent_id).and_then(|node| if let NodeExpr(parent) = node { Some(parent) } else { None } ) } @@ -77,7 +77,7 @@ pub fn span_lint(cx: &Context, lint: &'static Lint, sp: Span, msg: &str) { cx.span_lint(lint, sp, msg); } -pub fn span_help_and_lint(cx: &Context, lint: &'static Lint, span: Span, +pub fn span_help_and_lint(cx: &Context, lint: &'static Lint, span: Span, msg: &str, help: &str) { span_lint(cx, lint, span, msg); if cx.current_level(lint) != Level::Allow { diff --git a/tests/compile-fail/approx_const.rs b/tests/compile-fail/approx_const.rs old mode 100644 new mode 100755 index 488c8f16f5b..3eb170b295b --- a/tests/compile-fail/approx_const.rs +++ b/tests/compile-fail/approx_const.rs @@ -4,53 +4,53 @@ #[deny(approx_constant)] #[allow(unused)] fn main() { - let my_e = 2.7182; //~ERROR - let almost_e = 2.718; //~ERROR - let no_e = 2.71; - - let my_1_frac_pi = 0.3183; //~ERROR - let no_1_frac_pi = 0.31; + let my_e = 2.7182; //~ERROR + let almost_e = 2.718; //~ERROR + let no_e = 2.71; - let my_frac_1_sqrt_2 = 0.70710678; //~ERROR - let almost_frac_1_sqrt_2 = 0.70711; //~ERROR - let my_frac_1_sqrt_2 = 0.707; - - let my_frac_2_pi = 0.63661977; //~ERROR - let no_frac_2_pi = 0.636; - - let my_frac_2_sq_pi = 1.128379; //~ERROR - let no_frac_2_sq_pi = 1.128; + let my_1_frac_pi = 0.3183; //~ERROR + let no_1_frac_pi = 0.31; - let my_frac_2_pi = 1.57079632679; //~ERROR - let no_frac_2_pi = 1.5705; - - let my_frac_3_pi = 1.04719755119; //~ERROR - let no_frac_3_pi = 1.047; - - let my_frac_4_pi = 0.785398163397; //~ERROR - let no_frac_4_pi = 0.785; + let my_frac_1_sqrt_2 = 0.70710678; //~ERROR + let almost_frac_1_sqrt_2 = 0.70711; //~ERROR + let my_frac_1_sqrt_2 = 0.707; - let my_frac_6_pi = 0.523598775598; //~ERROR - let no_frac_6_pi = 0.523; + let my_frac_2_pi = 0.63661977; //~ERROR + let no_frac_2_pi = 0.636; - let my_frac_8_pi = 0.3926990816987; //~ERROR - let no_frac_8_pi = 0.392; + let my_frac_2_sq_pi = 1.128379; //~ERROR + let no_frac_2_sq_pi = 1.128; - let my_ln_10 = 2.302585092994046; //~ERROR - let no_ln_10 = 2.303; - - let my_ln_2 = 0.6931471805599453; //~ERROR - let no_ln_2 = 0.693; + let my_frac_2_pi = 1.57079632679; //~ERROR + let no_frac_2_pi = 1.5705; - let my_log10_e = 0.43429448190325176; //~ERROR - let no_log10_e = 0.434; - - let my_log2_e = 1.4426950408889634; //~ERROR - let no_log2_e = 1.442; - - let my_pi = 3.1415; //~ERROR - let almost_pi = 3.141; - - let my_sq2 = 1.4142; //~ERROR - let no_sq2 = 1.414; + let my_frac_3_pi = 1.04719755119; //~ERROR + let no_frac_3_pi = 1.047; + + let my_frac_4_pi = 0.785398163397; //~ERROR + let no_frac_4_pi = 0.785; + + let my_frac_6_pi = 0.523598775598; //~ERROR + let no_frac_6_pi = 0.523; + + let my_frac_8_pi = 0.3926990816987; //~ERROR + let no_frac_8_pi = 0.392; + + let my_ln_10 = 2.302585092994046; //~ERROR + let no_ln_10 = 2.303; + + let my_ln_2 = 0.6931471805599453; //~ERROR + let no_ln_2 = 0.693; + + let my_log10_e = 0.43429448190325176; //~ERROR + let no_log10_e = 0.434; + + let my_log2_e = 1.4426950408889634; //~ERROR + let no_log2_e = 1.442; + + let my_pi = 3.1415; //~ERROR + let almost_pi = 3.141; + + let my_sq2 = 1.4142; //~ERROR + let no_sq2 = 1.414; } diff --git a/tests/compile-fail/attrs.rs b/tests/compile-fail/attrs.rs old mode 100644 new mode 100755 index 9b648a517e0..42bb0fca6dc --- a/tests/compile-fail/attrs.rs +++ b/tests/compile-fail/attrs.rs @@ -5,29 +5,29 @@ #[inline(always)] //~ERROR You have declared #[inline(always)] on test_attr_lint. fn test_attr_lint() { - assert!(true) + assert!(true) } #[inline(always)] fn false_positive_expr() { - unreachable!() + unreachable!() } #[inline(always)] fn false_positive_stmt() { - unreachable!(); + unreachable!(); } #[inline(always)] fn empty_and_false_positive_stmt() { - ; - unreachable!(); + ; + unreachable!(); } fn main() { - test_attr_lint(); - if false { false_positive_expr() } - if false { false_positive_stmt() } - if false { empty_and_false_positive_stmt() } + test_attr_lint(); + if false { false_positive_expr() } + if false { false_positive_stmt() } + if false { empty_and_false_positive_stmt() } } diff --git a/tests/compile-fail/bit_masks.rs b/tests/compile-fail/bit_masks.rs old mode 100644 new mode 100755 index e6b89b98564..c2a82483005 --- a/tests/compile-fail/bit_masks.rs +++ b/tests/compile-fail/bit_masks.rs @@ -7,47 +7,47 @@ const EVEN_MORE_REDIRECTION : i64 = THREE_BITS; #[deny(bad_bit_mask)] #[allow(ineffective_bit_mask, identity_op)] fn main() { - let x = 5; - - x & 0 == 0; //~ERROR &-masking with zero - x & 1 == 1; //ok, distinguishes bit 0 - x & 1 == 0; //ok, compared with zero - x & 2 == 1; //~ERROR - x | 0 == 0; //ok, equals x == 0 (maybe warn?) - x | 1 == 3; //ok, equals x == 2 || x == 3 - x | 3 == 3; //ok, equals x <= 3 - x | 3 == 2; //~ERROR + let x = 5; - x & 1 > 1; //~ERROR - x & 2 > 1; // ok, distinguishes x & 2 == 2 from x & 2 == 0 - x & 2 < 1; // ok, distinguishes x & 2 == 2 from x & 2 == 0 - x | 1 > 1; // ok (if a bit silly), equals x > 1 - x | 2 > 1; //~ERROR - x | 2 <= 2; // ok (if a bit silly), equals x <= 2 - - // this also now works with constants - x & THREE_BITS == 8; //~ERROR - x | EVEN_MORE_REDIRECTION < 7; //~ERROR - - 0 & x == 0; //~ERROR - 1 | x > 1; - - // and should now also match uncommon usage - 1 < 2 | x; //~ERROR - 2 == 3 | x; //~ERROR - 1 == x & 2; //~ERROR - - x | 1 > 2; // no error, because we allowed ineffective bit masks - ineffective(); + x & 0 == 0; //~ERROR &-masking with zero + x & 1 == 1; //ok, distinguishes bit 0 + x & 1 == 0; //ok, compared with zero + x & 2 == 1; //~ERROR + x | 0 == 0; //ok, equals x == 0 (maybe warn?) + x | 1 == 3; //ok, equals x == 2 || x == 3 + x | 3 == 3; //ok, equals x <= 3 + x | 3 == 2; //~ERROR + + x & 1 > 1; //~ERROR + x & 2 > 1; // ok, distinguishes x & 2 == 2 from x & 2 == 0 + x & 2 < 1; // ok, distinguishes x & 2 == 2 from x & 2 == 0 + x | 1 > 1; // ok (if a bit silly), equals x > 1 + x | 2 > 1; //~ERROR + x | 2 <= 2; // ok (if a bit silly), equals x <= 2 + + // this also now works with constants + x & THREE_BITS == 8; //~ERROR + x | EVEN_MORE_REDIRECTION < 7; //~ERROR + + 0 & x == 0; //~ERROR + 1 | x > 1; + + // and should now also match uncommon usage + 1 < 2 | x; //~ERROR + 2 == 3 | x; //~ERROR + 1 == x & 2; //~ERROR + + x | 1 > 2; // no error, because we allowed ineffective bit masks + ineffective(); } #[deny(ineffective_bit_mask)] #[allow(bad_bit_mask)] fn ineffective() { - let x = 5; - - x | 1 > 2; //~ERROR - x | 1 < 3; //~ERROR - x | 1 <= 3; //~ERROR - x | 1 >= 2; //~ERROR + let x = 5; + + x | 1 > 2; //~ERROR + x | 1 < 3; //~ERROR + x | 1 <= 3; //~ERROR + x | 1 >= 2; //~ERROR } diff --git a/tests/compile-fail/box_vec.rs b/tests/compile-fail/box_vec.rs old mode 100644 new mode 100755 index 51d21f5537a..7d80dd86d22 --- a/tests/compile-fail/box_vec.rs +++ b/tests/compile-fail/box_vec.rs @@ -8,7 +8,7 @@ pub fn test(foo: Box>) { //~ ERROR You seem to be trying to use Box)>) { // pass if #31 is fixed - foo(vec![1, 2, 3]) + foo(vec![1, 2, 3]) } fn main(){ diff --git a/tests/compile-fail/cmp_nan.rs b/tests/compile-fail/cmp_nan.rs old mode 100644 new mode 100755 index 69631331467..b6549c2c1fb --- a/tests/compile-fail/cmp_nan.rs +++ b/tests/compile-fail/cmp_nan.rs @@ -4,19 +4,19 @@ #[deny(cmp_nan)] #[allow(float_cmp)] fn main() { - let x = 5f32; - x == std::f32::NAN; //~ERROR - x != std::f32::NAN; //~ERROR - x < std::f32::NAN; //~ERROR - x > std::f32::NAN; //~ERROR - x <= std::f32::NAN; //~ERROR - x >= std::f32::NAN; //~ERROR + let x = 5f32; + x == std::f32::NAN; //~ERROR + x != std::f32::NAN; //~ERROR + x < std::f32::NAN; //~ERROR + x > std::f32::NAN; //~ERROR + x <= std::f32::NAN; //~ERROR + x >= std::f32::NAN; //~ERROR - let y = 0f64; - y == std::f64::NAN; //~ERROR - y != std::f64::NAN; //~ERROR - y < std::f64::NAN; //~ERROR - y > std::f64::NAN; //~ERROR - y <= std::f64::NAN; //~ERROR - y >= std::f64::NAN; //~ERROR + let y = 0f64; + y == std::f64::NAN; //~ERROR + y != std::f64::NAN; //~ERROR + y < std::f64::NAN; //~ERROR + y > std::f64::NAN; //~ERROR + y <= std::f64::NAN; //~ERROR + y >= std::f64::NAN; //~ERROR } diff --git a/tests/compile-fail/cmp_owned.rs b/tests/compile-fail/cmp_owned.rs old mode 100644 new mode 100755 index d7399e6d3aa..5951dc1bbd7 --- a/tests/compile-fail/cmp_owned.rs +++ b/tests/compile-fail/cmp_owned.rs @@ -3,21 +3,21 @@ #[deny(cmp_owned)] fn main() { - let x = "oh"; - - #[allow(str_to_string)] - fn with_to_string(x : &str) { - x != "foo".to_string(); //~ERROR this creates an owned instance - } - with_to_string(x); - - x != "foo".to_owned(); //~ERROR this creates an owned instance - - #[allow(deprecated)] // for from_str - fn old_timey(x : &str) { - x != String::from_str("foo"); //~ERROR this creates an owned instance - } - old_timey(x); - - x != String::from("foo"); //~ERROR this creates an owned instance + let x = "oh"; + + #[allow(str_to_string)] + fn with_to_string(x : &str) { + x != "foo".to_string(); //~ERROR this creates an owned instance + } + with_to_string(x); + + x != "foo".to_owned(); //~ERROR this creates an owned instance + + #[allow(deprecated)] // for from_str + fn old_timey(x : &str) { + x != String::from_str("foo"); //~ERROR this creates an owned instance + } + old_timey(x); + + x != String::from("foo"); //~ERROR this creates an owned instance } diff --git a/tests/compile-fail/collapsible_if.rs b/tests/compile-fail/collapsible_if.rs old mode 100644 new mode 100755 index 7b7ff13f24b..280744b5b45 --- a/tests/compile-fail/collapsible_if.rs +++ b/tests/compile-fail/collapsible_if.rs @@ -34,10 +34,10 @@ fn main() { } } - if x == "hello" { - print!("Hello "); - if y == "world" { - println!("world!") - } - } + if x == "hello" { + print!("Hello "); + if y == "world" { + println!("world!") + } + } } diff --git a/tests/compile-fail/eq_op.rs b/tests/compile-fail/eq_op.rs old mode 100644 new mode 100755 index 07b15625b2c..45fce0c0bb3 --- a/tests/compile-fail/eq_op.rs +++ b/tests/compile-fail/eq_op.rs @@ -2,35 +2,35 @@ #![plugin(clippy)] fn id(x: X) -> X { - x + x } #[deny(eq_op)] #[allow(identity_op)] fn main() { - // simple values and comparisons - 1 == 1; //~ERROR - "no" == "no"; //~ERROR - // even though I agree that no means no ;-) - false != false; //~ERROR - 1.5 < 1.5; //~ERROR - 1u64 >= 1u64; //~ERROR - - // casts, methods, parenthesis - (1 as u64) & (1 as u64); //~ERROR - 1 ^ ((((((1)))))); //~ERROR - id((1)) | id(1); //~ERROR - - // unary and binary operators - (-(2) < -(2)); //~ERROR + // simple values and comparisons + 1 == 1; //~ERROR + "no" == "no"; //~ERROR + // even though I agree that no means no ;-) + false != false; //~ERROR + 1.5 < 1.5; //~ERROR + 1u64 >= 1u64; //~ERROR + + // casts, methods, parenthesis + (1 as u64) & (1 as u64); //~ERROR + 1 ^ ((((((1)))))); //~ERROR + id((1)) | id(1); //~ERROR + + // unary and binary operators + (-(2) < -(2)); //~ERROR ((1 + 1) & (1 + 1) == (1 + 1) & (1 + 1)); //~^ ERROR //~^^ ERROR //~^^^ ERROR - (1 * 2) + (3 * 4) == 1 * 2 + 3 * 4; //~ERROR - - // various other things - ([1] != [1]); //~ERROR + (1 * 2) + (3 * 4) == 1 * 2 + 3 * 4; //~ERROR + + // various other things + ([1] != [1]); //~ERROR ((1, 2) != (1, 2)); //~ERROR [1].len() == [1].len(); //~ERROR vec![1, 2, 3] == vec![1, 2, 3]; //no error yet, as we don't match macros diff --git a/tests/compile-fail/float_cmp.rs b/tests/compile-fail/float_cmp.rs old mode 100644 new mode 100755 index dce8dba1ebe..2305e42161a --- a/tests/compile-fail/float_cmp.rs +++ b/tests/compile-fail/float_cmp.rs @@ -7,29 +7,29 @@ const ZERO : f32 = 0.0; const ONE : f32 = ZERO + 1.0; fn twice(x : T) -> T where T : Add, T : Copy { - x + x + x + x } #[deny(float_cmp)] #[allow(unused)] fn main() { - ZERO == 0f32; //~ERROR - ZERO == 0.0; //~ERROR - ZERO + ZERO != 1.0; //~ERROR - - ONE != 0.0; //~ERROR - twice(ONE) != ONE; //~ERROR - ONE as f64 != 0.0; //~ERROR - - let x : f64 = 1.0; - - x == 1.0; //~ERROR - x != 0f64; //~ERROR - - twice(x) != twice(ONE as f64); //~ERROR - - x < 0.0; - x > 0.0; - x <= 0.0; - x >= 0.0; + ZERO == 0f32; //~ERROR + ZERO == 0.0; //~ERROR + ZERO + ZERO != 1.0; //~ERROR + + ONE != 0.0; //~ERROR + twice(ONE) != ONE; //~ERROR + ONE as f64 != 0.0; //~ERROR + + let x : f64 = 1.0; + + x == 1.0; //~ERROR + x != 0f64; //~ERROR + + twice(x) != twice(ONE as f64); //~ERROR + + x < 0.0; + x > 0.0; + x <= 0.0; + x >= 0.0; } diff --git a/tests/compile-fail/identity_op.rs b/tests/compile-fail/identity_op.rs old mode 100644 new mode 100755 index 6c17d30fac4..cde4a615b25 --- a/tests/compile-fail/identity_op.rs +++ b/tests/compile-fail/identity_op.rs @@ -7,18 +7,18 @@ const ZERO : i64 = 0; #[deny(identity_op)] fn main() { - let x = 0; - - x + 0; //~ERROR - 0 + x; //~ERROR - x - ZERO; //~ERROR - x | (0); //~ERROR - ((ZERO)) | x; //~ERROR - - x * 1; //~ERROR - 1 * x; //~ERROR - x / ONE; //~ERROR - - x & NEG_ONE; //~ERROR - -1 & x; //~ERROR + let x = 0; + + x + 0; //~ERROR + 0 + x; //~ERROR + x - ZERO; //~ERROR + x | (0); //~ERROR + ((ZERO)) | x; //~ERROR + + x * 1; //~ERROR + 1 * x; //~ERROR + x / ONE; //~ERROR + + x & NEG_ONE; //~ERROR + -1 & x; //~ERROR } diff --git a/tests/compile-fail/len_zero.rs b/tests/compile-fail/len_zero.rs old mode 100644 new mode 100755 index e64010d334d..48a10042658 --- a/tests/compile-fail/len_zero.rs +++ b/tests/compile-fail/len_zero.rs @@ -5,98 +5,98 @@ struct One; #[deny(len_without_is_empty)] impl One { - fn len(self: &Self) -> isize { //~ERROR Item 'One' has a '.len(_: &Self)' - 1 - } + fn len(self: &Self) -> isize { //~ERROR Item 'One' has a '.len(_: &Self)' + 1 + } } #[deny(len_without_is_empty)] trait TraitsToo { - fn len(self: &Self) -> isize; //~ERROR Trait 'TraitsToo' has a '.len(_: + fn len(self: &Self) -> isize; //~ERROR Trait 'TraitsToo' has a '.len(_: } impl TraitsToo for One { - fn len(self: &Self) -> isize { - 0 - } + fn len(self: &Self) -> isize { + 0 + } } struct HasIsEmpty; #[deny(len_without_is_empty)] impl HasIsEmpty { - fn len(self: &Self) -> isize { - 1 - } + fn len(self: &Self) -> isize { + 1 + } - fn is_empty(self: &Self) -> bool { - false - } + fn is_empty(self: &Self) -> bool { + false + } } struct Wither; #[deny(len_without_is_empty)] trait WithIsEmpty { - fn len(self: &Self) -> isize; - fn is_empty(self: &Self) -> bool; + fn len(self: &Self) -> isize; + fn is_empty(self: &Self) -> bool; } impl WithIsEmpty for Wither { - fn len(self: &Self) -> isize { - 1 - } + fn len(self: &Self) -> isize { + 1 + } - fn is_empty(self: &Self) -> bool { - false - } + fn is_empty(self: &Self) -> bool { + false + } } struct HasWrongIsEmpty; #[deny(len_without_is_empty)] impl HasWrongIsEmpty { - fn len(self: &Self) -> isize { //~ERROR Item 'HasWrongIsEmpty' has a '.len(_: &Self)' - 1 - } - - #[allow(dead_code, unused)] - fn is_empty(self: &Self, x : u32) -> bool { - false - } + fn len(self: &Self) -> isize { //~ERROR Item 'HasWrongIsEmpty' has a '.len(_: &Self)' + 1 + } + + #[allow(dead_code, unused)] + fn is_empty(self: &Self, x : u32) -> bool { + false + } } #[deny(len_zero)] fn main() { - let x = [1, 2]; - if x.len() == 0 { //~ERROR Consider replacing the len comparison - println!("This should not happen!"); - } - - let y = One; - if y.len() == 0 { //no error because One does not have .is_empty() - println!("This should not happen either!"); - } - - let z : &TraitsToo = &y; - if z.len() > 0 { //no error, because TraitsToo has no .is_empty() method - println!("Nor should this!"); - } - - let hie = HasIsEmpty; - if hie.len() == 0 { //~ERROR Consider replacing the len comparison - println!("Or this!"); - } - assert!(!hie.is_empty()); - - let wie : &WithIsEmpty = &Wither; - if wie.len() == 0 { //~ERROR Consider replacing the len comparison - println!("Or this!"); - } - assert!(!wie.is_empty()); - - let hwie = HasWrongIsEmpty; - if hwie.len() == 0 { //no error as HasWrongIsEmpty does not have .is_empty() - println!("Or this!"); - } + let x = [1, 2]; + if x.len() == 0 { //~ERROR Consider replacing the len comparison + println!("This should not happen!"); + } + + let y = One; + if y.len() == 0 { //no error because One does not have .is_empty() + println!("This should not happen either!"); + } + + let z : &TraitsToo = &y; + if z.len() > 0 { //no error, because TraitsToo has no .is_empty() method + println!("Nor should this!"); + } + + let hie = HasIsEmpty; + if hie.len() == 0 { //~ERROR Consider replacing the len comparison + println!("Or this!"); + } + assert!(!hie.is_empty()); + + let wie : &WithIsEmpty = &Wither; + if wie.len() == 0 { //~ERROR Consider replacing the len comparison + println!("Or this!"); + } + assert!(!wie.is_empty()); + + let hwie = HasWrongIsEmpty; + if hwie.len() == 0 { //no error as HasWrongIsEmpty does not have .is_empty() + println!("Or this!"); + } } diff --git a/tests/compile-fail/mut_mut.rs b/tests/compile-fail/mut_mut.rs old mode 100644 new mode 100755 index d7adc067740..2a3f7e3958c --- a/tests/compile-fail/mut_mut.rs +++ b/tests/compile-fail/mut_mut.rs @@ -6,29 +6,29 @@ #[deny(mut_mut)] fn fun(x : &mut &mut u32) -> bool { //~ERROR - **x > 0 + **x > 0 } macro_rules! mut_ptr { - ($p:expr) => { &mut $p } -} + ($p:expr) => { &mut $p } +} #[deny(mut_mut)] #[allow(unused_mut, unused_variables)] fn main() { - let mut x = &mut &mut 1u32; //~ERROR - { - let mut y = &mut x; //~ERROR - } - - if fun(x) { - let y : &mut &mut &mut u32 = &mut &mut &mut 2; - //~^ ERROR - //~^^ ERROR - //~^^^ ERROR - //~^^^^ ERROR - ***y + **x; - } - - let mut z = mut_ptr!(&mut 3u32); //~ERROR + let mut x = &mut &mut 1u32; //~ERROR + { + let mut y = &mut x; //~ERROR + } + + if fun(x) { + let y : &mut &mut &mut u32 = &mut &mut &mut 2; + //~^ ERROR + //~^^ ERROR + //~^^^ ERROR + //~^^^^ ERROR + ***y + **x; + } + + let mut z = mut_ptr!(&mut 3u32); //~ERROR } diff --git a/tests/compile-fail/needless_bool.rs b/tests/compile-fail/needless_bool.rs old mode 100644 new mode 100755 index 97a478ee410..88919f39d6d --- a/tests/compile-fail/needless_bool.rs +++ b/tests/compile-fail/needless_bool.rs @@ -3,10 +3,10 @@ #[deny(needless_bool)] fn main() { - let x = true; - if x { true } else { true }; //~ERROR - if x { false } else { false }; //~ERROR - if x { true } else { false }; //~ERROR - if x { false } else { true }; //~ERROR - if x { x } else { false }; // would also be questionable, but we don't catch this yet + let x = true; + if x { true } else { true }; //~ERROR + if x { false } else { false }; //~ERROR + if x { true } else { false }; //~ERROR + if x { false } else { true }; //~ERROR + if x { x } else { false }; // would also be questionable, but we don't catch this yet } diff --git a/tests/compile-fail/precedence.rs b/tests/compile-fail/precedence.rs old mode 100644 new mode 100755 index 7969be0f371..fb7d06214a2 --- a/tests/compile-fail/precedence.rs +++ b/tests/compile-fail/precedence.rs @@ -4,7 +4,7 @@ #[deny(precedence)] #[allow(eq_op)] fn main() { - format!("{} vs. {}", 1 << 2 + 3, (1 << 2) + 3); //~ERROR + format!("{} vs. {}", 1 << 2 + 3, (1 << 2) + 3); //~ERROR format!("{} vs. {}", 1 + 2 << 3, 1 + (2 << 3)); //~ERROR format!("{} vs. {}", 4 >> 1 + 1, (4 >> 1) + 1); //~ERROR format!("{} vs. {}", 1 + 3 >> 2, 1 + (3 >> 2)); //~ERROR diff --git a/tests/compile-fail/ptr_arg.rs b/tests/compile-fail/ptr_arg.rs old mode 100644 new mode 100755 index 2fe36eafa6c..7ba291b1439 --- a/tests/compile-fail/ptr_arg.rs +++ b/tests/compile-fail/ptr_arg.rs @@ -4,17 +4,17 @@ #[deny(ptr_arg)] #[allow(unused)] fn do_vec(x: &Vec) { //~ERROR: Writing '&Vec<_>' instead of '&[_]' - //Nothing here + //Nothing here } #[deny(ptr_arg)] #[allow(unused)] fn do_str(x: &String) { //~ERROR - //Nothing here either + //Nothing here either } fn main() { - let x = vec![1i64, 2, 3]; - do_vec(&x); - do_str(&"hello".to_owned()); + let x = vec![1i64, 2, 3]; + do_vec(&x); + do_str(&"hello".to_owned()); } diff --git a/tests/compile-fail/strings.rs b/tests/compile-fail/strings.rs old mode 100644 new mode 100755 index 2b200f1d07e..4b6f0bc884f --- a/tests/compile-fail/strings.rs +++ b/tests/compile-fail/strings.rs @@ -4,9 +4,9 @@ #![deny(string_add_assign)] fn main() { - let x = "".to_owned(); - - for i in (1..3) { - x = x + "."; //~ERROR - } + let x = "".to_owned(); + + for i in (1..3) { + x = x + "."; //~ERROR + } } diff --git a/tests/compile-fail/unicode.rs b/tests/compile-fail/unicode.rs old mode 100644 new mode 100755 index 0385f45cc5e..a121b985f09 --- a/tests/compile-fail/unicode.rs +++ b/tests/compile-fail/unicode.rs @@ -3,23 +3,23 @@ #[deny(zero_width_space)] fn zero() { - print!("Here >​< is a ZWS, and ​another"); - //~^ ERROR Zero-width space detected. Consider using \u{200B} - //~^^ ERROR Zero-width space detected. Consider using \u{200B} + print!("Here >​< is a ZWS, and ​another"); + //~^ ERROR Zero-width space detected. Consider using \u{200B} + //~^^ ERROR Zero-width space detected. Consider using \u{200B} } //#[deny(unicode_canon)] fn canon() { - print!("̀ah?"); //not yet ~ERROR Non-canonical unicode sequence detected. Consider using à + print!("̀ah?"); //not yet ~ERROR Non-canonical unicode sequence detected. Consider using à } //#[deny(ascii_only)] fn uni() { - println!("Üben!"); //not yet ~ERROR Unicode literal detected. Consider using \u{FC} + println!("Üben!"); //not yet ~ERROR Unicode literal detected. Consider using \u{FC} } fn main() { - zero(); - uni(); - canon(); + zero(); + uni(); + canon(); } diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 4af4ea7673a..602937a40af 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -5,13 +5,13 @@ use std::env::var; fn run_mode(mode: &'static str) { let mut config = compiletest::default_config(); - + let cfg_mode = mode.parse().ok().expect("Invalid mode"); config.target_rustcflags = Some("-L target/debug/".to_owned()); - if let Ok(name) = var::<&str>("TESTNAME") { - let s : String = name.to_owned(); - config.filter = Some(s) - } + if let Ok(name) = var::<&str>("TESTNAME") { + let s : String = name.to_owned(); + config.filter = Some(s) + } config.mode = cfg_mode; config.src_base = PathBuf::from(format!("tests/{}", mode)); diff --git a/tests/mut_mut_macro.rs b/tests/mut_mut_macro.rs old mode 100644 new mode 100755 index 32fdea3a340..ebfd3ed2e1f --- a/tests/mut_mut_macro.rs +++ b/tests/mut_mut_macro.rs @@ -10,22 +10,22 @@ use std::collections::HashMap; #[test] #[deny(mut_mut)] fn test_regex() { - let pattern = regex!(r"^(?P[#]+)\s(?P.+)$"); - assert!(pattern.is_match("# headline")); + let pattern = regex!(r"^(?P<level>[#]+)\s(?P<title>.+)$"); + assert!(pattern.is_match("# headline")); } #[test] #[deny(mut_mut)] #[allow(unused_variables, unused_mut)] fn test_lazy_static() { - lazy_static! { - static ref MUT_MAP : HashMap<usize, &'static str> = { - let mut m = HashMap::new(); - let mut zero = &mut &mut "zero"; - m.insert(0, "zero"); - m - }; - static ref MUT_COUNT : usize = MUT_MAP.len(); - } - assert!(*MUT_COUNT == 1); + lazy_static! { + static ref MUT_MAP : HashMap<usize, &'static str> = { + let mut m = HashMap::new(); + let mut zero = &mut &mut "zero"; + m.insert(0, "zero"); + m + }; + static ref MUT_COUNT : usize = MUT_MAP.len(); + } + assert!(*MUT_COUNT == 1); }