parent
cca6eb2e2b
commit
90453fd893
|
@ -38,7 +38,7 @@ declare_restriction_lint! {
|
||||||
|
|
||||||
#[derive(Copy, Clone, Default)]
|
#[derive(Copy, Clone, Default)]
|
||||||
pub struct Arithmetic {
|
pub struct Arithmetic {
|
||||||
span: Option<Span>
|
span: Option<Span>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LintPass for Arithmetic {
|
impl LintPass for Arithmetic {
|
||||||
|
@ -49,48 +49,36 @@ impl LintPass for Arithmetic {
|
||||||
|
|
||||||
impl LateLintPass for Arithmetic {
|
impl LateLintPass for Arithmetic {
|
||||||
fn check_expr(&mut self, cx: &LateContext, expr: &hir::Expr) {
|
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 {
|
match expr.node {
|
||||||
hir::ExprBinary(ref op, ref l, ref r) => {
|
hir::ExprBinary(ref op, ref l, ref r) => {
|
||||||
match op.node {
|
match op.node {
|
||||||
hir::BiAnd | hir::BiOr | hir::BiBitAnd |
|
hir::BiAnd | hir::BiOr | hir::BiBitAnd | hir::BiBitOr | hir::BiBitXor | hir::BiShl |
|
||||||
hir::BiBitOr | hir::BiBitXor | hir::BiShl | hir::BiShr |
|
hir::BiShr | hir::BiEq | hir::BiLt | hir::BiLe | hir::BiNe | hir::BiGe | hir::BiGt => return,
|
||||||
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));
|
let (l_ty, r_ty) = (cx.tcx.expr_ty(l), cx.tcx.expr_ty(r));
|
||||||
if l_ty.is_integral() && r_ty.is_integral() {
|
if l_ty.is_integral() && r_ty.is_integral() {
|
||||||
span_lint(cx,
|
span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
|
||||||
INTEGER_ARITHMETIC,
|
|
||||||
expr.span,
|
|
||||||
"integer arithmetic detected");
|
|
||||||
self.span = Some(expr.span);
|
self.span = Some(expr.span);
|
||||||
} else if l_ty.is_floating_point() && r_ty.is_floating_point() {
|
} else if l_ty.is_floating_point() && r_ty.is_floating_point() {
|
||||||
span_lint(cx,
|
span_lint(cx, FLOAT_ARITHMETIC, expr.span, "floating-point arithmetic detected");
|
||||||
FLOAT_ARITHMETIC,
|
|
||||||
expr.span,
|
|
||||||
"floating-point arithmetic detected");
|
|
||||||
self.span = Some(expr.span);
|
self.span = Some(expr.span);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
hir::ExprUnary(hir::UnOp::UnNeg, ref arg) => {
|
hir::ExprUnary(hir::UnOp::UnNeg, ref arg) => {
|
||||||
let ty = cx.tcx.expr_ty(arg);
|
let ty = cx.tcx.expr_ty(arg);
|
||||||
if ty.is_integral() {
|
if ty.is_integral() {
|
||||||
span_lint(cx,
|
span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
|
||||||
INTEGER_ARITHMETIC,
|
|
||||||
expr.span,
|
|
||||||
"integer arithmetic detected");
|
|
||||||
self.span = Some(expr.span);
|
self.span = Some(expr.span);
|
||||||
} else if ty.is_floating_point() {
|
} else if ty.is_floating_point() {
|
||||||
span_lint(cx,
|
span_lint(cx, FLOAT_ARITHMETIC, expr.span, "floating-point arithmetic detected");
|
||||||
FLOAT_ARITHMETIC,
|
|
||||||
expr.span,
|
|
||||||
"floating-point arithmetic detected");
|
|
||||||
self.span = Some(expr.span);
|
self.span = Some(expr.span);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
_ => ()
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -79,11 +79,11 @@ impl LateLintPass for ArrayIndexing {
|
||||||
// Index is a constant range
|
// Index is a constant range
|
||||||
if let Some(range) = utils::unsugar_range(index) {
|
if let Some(range) = utils::unsugar_range(index) {
|
||||||
let start = range.start
|
let start = range.start
|
||||||
.map(|start| eval_const_expr_partial(cx.tcx, start, ExprTypeChecked, None))
|
.map(|start| eval_const_expr_partial(cx.tcx, start, ExprTypeChecked, None))
|
||||||
.map(|v| v.ok());
|
.map(|v| v.ok());
|
||||||
let end = range.end
|
let end = range.end
|
||||||
.map(|end| eval_const_expr_partial(cx.tcx, end, ExprTypeChecked, None))
|
.map(|end| eval_const_expr_partial(cx.tcx, end, ExprTypeChecked, None))
|
||||||
.map(|v| v.ok());
|
.map(|v| v.ok());
|
||||||
|
|
||||||
if let Some((start, end)) = to_const_range(start, end, range.limits, size) {
|
if let Some((start, end)) = to_const_range(start, end, range.limits, size) {
|
||||||
if start > size || end > size {
|
if start > size || end > size {
|
||||||
|
|
|
@ -51,31 +51,24 @@ impl LateLintPass for AssignOps {
|
||||||
match expr.node {
|
match expr.node {
|
||||||
hir::ExprAssignOp(op, ref lhs, ref rhs) => {
|
hir::ExprAssignOp(op, ref lhs, ref rhs) => {
|
||||||
if let (Some(l), Some(r)) = (snippet_opt(cx, lhs.span), snippet_opt(cx, rhs.span)) {
|
if let (Some(l), Some(r)) = (snippet_opt(cx, lhs.span), snippet_opt(cx, rhs.span)) {
|
||||||
span_lint_and_then(cx,
|
span_lint_and_then(cx, ASSIGN_OPS, expr.span, "assign operation detected", |db| {
|
||||||
ASSIGN_OPS,
|
match rhs.node {
|
||||||
expr.span,
|
hir::ExprBinary(op2, _, _) if op2 != op => {
|
||||||
"assign operation detected",
|
db.span_suggestion(expr.span,
|
||||||
|db| {
|
"replace it with",
|
||||||
match rhs.node {
|
format!("{} = {} {} ({})", l, l, op.node.as_str(), r));
|
||||||
hir::ExprBinary(op2, _, _) if op2 != op => {
|
}
|
||||||
db.span_suggestion(expr.span,
|
_ => {
|
||||||
"replace it with",
|
db.span_suggestion(expr.span,
|
||||||
format!("{} = {} {} ({})", l, l, op.node.as_str(), r));
|
"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 {
|
} else {
|
||||||
span_lint(cx,
|
span_lint(cx, ASSIGN_OPS, expr.span, "assign operation detected");
|
||||||
ASSIGN_OPS,
|
|
||||||
expr.span,
|
|
||||||
"assign operation detected");
|
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
hir::ExprAssign(ref assignee, ref e) => {
|
hir::ExprAssign(ref assignee, ref e) => {
|
||||||
if let hir::ExprBinary(op, ref l, ref r) = e.node {
|
if let hir::ExprBinary(op, ref l, ref r) = e.node {
|
||||||
let lint = |assignee: &hir::Expr, rhs: &hir::Expr| {
|
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,
|
if ops!(op.node,
|
||||||
Sub:BiSub,
|
cx,
|
||||||
Mul:BiMul,
|
ty,
|
||||||
Div:BiDiv,
|
rty,
|
||||||
Rem:BiRem,
|
Add: BiAdd,
|
||||||
And:BiAnd,
|
Sub: BiSub,
|
||||||
Or:BiOr,
|
Mul: BiMul,
|
||||||
BitAnd:BiBitAnd,
|
Div: BiDiv,
|
||||||
BitOr:BiBitOr,
|
Rem: BiRem,
|
||||||
BitXor:BiBitXor,
|
And: BiAnd,
|
||||||
Shr:BiShr,
|
Or: BiOr,
|
||||||
Shl:BiShl
|
BitAnd: BiBitAnd,
|
||||||
) {
|
BitOr: BiBitOr,
|
||||||
if let (Some(snip_a), Some(snip_r)) = (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span)) {
|
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,
|
span_lint_and_then(cx,
|
||||||
ASSIGN_OP_PATTERN,
|
ASSIGN_OP_PATTERN,
|
||||||
expr.span,
|
expr.span,
|
||||||
"manual implementation of an assign operation",
|
"manual implementation of an assign operation",
|
||||||
|db| {
|
|db| {
|
||||||
db.span_suggestion(expr.span,
|
db.span_suggestion(expr.span,
|
||||||
"replace it with",
|
"replace it with",
|
||||||
format!("{} {}= {}", snip_a, op.node.as_str(), snip_r));
|
format!("{} {}= {}", snip_a, op.node.as_str(), snip_r));
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
span_lint(cx,
|
span_lint(cx,
|
||||||
|
@ -142,17 +139,16 @@ impl LateLintPass for AssignOps {
|
||||||
// a = b commutative_op a
|
// a = b commutative_op a
|
||||||
if SpanlessEq::new(cx).ignore_fn().eq_expr(assignee, r) {
|
if SpanlessEq::new(cx).ignore_fn().eq_expr(assignee, r) {
|
||||||
match op.node {
|
match op.node {
|
||||||
hir::BiAdd | hir::BiMul |
|
hir::BiAdd | hir::BiMul | hir::BiAnd | hir::BiOr | hir::BiBitXor | hir::BiBitAnd |
|
||||||
hir::BiAnd | hir::BiOr |
|
hir::BiBitOr => {
|
||||||
hir::BiBitXor | hir::BiBitAnd | hir::BiBitOr => {
|
|
||||||
lint(assignee, l);
|
lint(assignee, l);
|
||||||
},
|
}
|
||||||
_ => {},
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
_ => {},
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -322,7 +322,8 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> {
|
||||||
let simplified_stats = terminal_stats(suggestion);
|
let simplified_stats = terminal_stats(suggestion);
|
||||||
let mut improvement = false;
|
let mut improvement = false;
|
||||||
for i in 0..32 {
|
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] {
|
if stats.terminals[i] < simplified_stats.terminals[i] {
|
||||||
continue 'simplified;
|
continue 'simplified;
|
||||||
}
|
}
|
||||||
|
@ -332,17 +333,18 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> {
|
||||||
e.span,
|
e.span,
|
||||||
"this boolean expression contains a logic bug",
|
"this boolean expression contains a logic bug",
|
||||||
|db| {
|
|db| {
|
||||||
db.span_help(h2q.terminals[i].span,
|
db.span_help(h2q.terminals[i].span,
|
||||||
"this expression can be optimized out by applying \
|
"this expression can be optimized out by applying boolean operations to the \
|
||||||
boolean operations to the outer expression");
|
outer expression");
|
||||||
db.span_suggestion(e.span,
|
db.span_suggestion(e.span,
|
||||||
"it would look like the following",
|
"it would look like the following",
|
||||||
suggest(self.0, suggestion, &h2q.terminals));
|
suggest(self.0, suggestion, &h2q.terminals));
|
||||||
});
|
});
|
||||||
// don't also lint `NONMINIMAL_BOOL`
|
// don't also lint `NONMINIMAL_BOOL`
|
||||||
return;
|
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]) ||
|
improvement |= (stats.terminals[i] > simplified_stats.terminals[i]) ||
|
||||||
(stats.negations > simplified_stats.negations &&
|
(stats.negations > simplified_stats.negations &&
|
||||||
stats.ops == simplified_stats.ops) ||
|
stats.ops == simplified_stats.ops) ||
|
||||||
|
@ -358,12 +360,10 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> {
|
||||||
e.span,
|
e.span,
|
||||||
"this boolean expression can be simplified",
|
"this boolean expression can be simplified",
|
||||||
|db| {
|
|db| {
|
||||||
for suggestion in &improvements {
|
for suggestion in &improvements {
|
||||||
db.span_suggestion(e.span,
|
db.span_suggestion(e.span, "try", suggest(self.0, suggestion, &h2q.terminals));
|
||||||
"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
|
/// **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
|
/// **Known problems:** Sometimes it's hard to find a way to reduce the complexity
|
||||||
///
|
///
|
||||||
|
@ -69,7 +70,7 @@ impl CyclomaticComplexity {
|
||||||
returns / 2
|
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);
|
report_cc_bug(cx, cc, match_arms, divergence, short_circuits, ret_adjust, span);
|
||||||
} else {
|
} else {
|
||||||
let mut rust_cc = cc + divergence - match_arms - short_circuits;
|
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,
|
match_arms: u64,
|
||||||
divergence: u64,
|
divergence: u64,
|
||||||
returns: 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 {
|
if cx.current_level(CYCLOMATIC_COMPLEXITY) != Level::Allow {
|
||||||
cx.sess().span_note_without_error(span,
|
cx.sess().span_note_without_error(span,
|
||||||
&format!("Clippy encountered a bug calculating cyclomatic complexity \
|
&format!("Clippy encountered a bug calculating cyclomatic complexity \
|
||||||
(hide this message with `#[allow(cyclomatic_complexity)]`): cc \
|
(hide this message with `#[allow(cyclomatic_complexity)]`): \
|
||||||
= {}, arms = {}, div = {}, shorts = {}, returns = {}. Please file a bug report.",
|
cc = {}, arms = {}, div = {}, shorts = {}, returns = {}. \
|
||||||
|
Please file a bug report.",
|
||||||
cc,
|
cc,
|
||||||
narms,
|
narms,
|
||||||
div,
|
div,
|
||||||
|
|
|
@ -84,7 +84,8 @@ impl LateLintPass for Derive {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Implementation of the `DERIVE_HASH_XOR_EQ` lint.
|
/// 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! {[
|
if_let_chain! {[
|
||||||
match_path(&trait_ref.path, &paths::HASH),
|
match_path(&trait_ref.path, &paths::HASH),
|
||||||
let Some(peq_trait_def_id) = cx.tcx.lang_items.eq_trait()
|
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
|
// Some types are not Clone by default but could be cloned `by hand` if necessary
|
||||||
match ty.sty {
|
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 variant in &def.variants {
|
||||||
for field in &variant.fields {
|
for field in &variant.fields {
|
||||||
match field.ty(cx.tcx, substs).sty {
|
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
|
/// First byte of the current potential match
|
||||||
current_word_begin: usize,
|
current_word_begin: usize,
|
||||||
/// List of lines and their associated span
|
/// 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
|
/// Index of the current line we are parsing
|
||||||
line: usize,
|
line: usize,
|
||||||
/// Whether we are in a link
|
/// Whether we are in a link
|
||||||
|
|
|
@ -42,7 +42,8 @@ impl LintPass for Functions {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass 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::*;
|
use rustc::hir::map::Node::*;
|
||||||
|
|
||||||
if let Some(NodeItem(ref item)) = cx.tcx.map.find(cx.tcx.map.get_parent_node(nodeid)) {
|
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 {
|
let mut v = UsedVisitor {
|
||||||
cx: cx,
|
cx: cx,
|
||||||
id: id,
|
id: id,
|
||||||
used: false
|
used: false,
|
||||||
};
|
};
|
||||||
hir::intravisit::walk_expr(&mut v, expr);
|
hir::intravisit::walk_expr(&mut v, expr);
|
||||||
v.used
|
v.used
|
||||||
|
|
|
@ -608,13 +608,13 @@ fn check_for_loop_over_map_kv(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Ex
|
||||||
expr.span,
|
expr.span,
|
||||||
&format!("you seem to want to iterate on a map's {}", kind),
|
&format!("you seem to want to iterate on a map's {}", kind),
|
||||||
|db| {
|
|db| {
|
||||||
db.span_suggestion(expr.span,
|
db.span_suggestion(expr.span,
|
||||||
"use the corresponding method",
|
"use the corresponding method",
|
||||||
format!("for {} in {}.{}() {{ .. }}",
|
format!("for {} in {}.{}() {{ .. }}",
|
||||||
snippet(cx, *pat_span, ".."),
|
snippet(cx, *pat_span, ".."),
|
||||||
snippet(cx, arg_span, ".."),
|
snippet(cx, arg_span, ".."),
|
||||||
kind));
|
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. \
|
"you seem to be trying to use match for destructuring a single pattern. \
|
||||||
Consider using `if let`",
|
Consider using `if let`",
|
||||||
|db| {
|
|db| {
|
||||||
db.span_suggestion(expr.span,
|
db.span_suggestion(expr.span,
|
||||||
"try this",
|
"try this",
|
||||||
format!("if let {} = {} {}{}",
|
format!("if let {} = {} {}{}",
|
||||||
snippet(cx, arms[0].pats[0].span, ".."),
|
snippet(cx, arms[0].pats[0].span, ".."),
|
||||||
snippet(cx, ex.span, ".."),
|
snippet(cx, ex.span, ".."),
|
||||||
expr_block(cx, &arms[0].body, None, ".."),
|
expr_block(cx, &arms[0].body, None, ".."),
|
||||||
els_str));
|
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 \
|
"you seem to be trying to use match for destructuring a single pattern. Consider \
|
||||||
using `if let`",
|
using `if let`",
|
||||||
|db| {
|
|db| {
|
||||||
db.span_suggestion(expr.span,
|
db.span_suggestion(expr.span,
|
||||||
"try this",
|
"try this",
|
||||||
format!("if let {} = {} {}{}",
|
format!("if let {} = {} {}{}",
|
||||||
snippet(cx, arms[0].pats[0].span, ".."),
|
snippet(cx, arms[0].pats[0].span, ".."),
|
||||||
snippet(cx, ex.span, ".."),
|
snippet(cx, ex.span, ".."),
|
||||||
expr_block(cx, &arms[0].body, None, ".."),
|
expr_block(cx, &arms[0].body, None, ".."),
|
||||||
els_str));
|
els_str));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ impl LateLintPass for MemForget {
|
||||||
|
|
||||||
if match forgot_ty.ty_adt_def() {
|
if match forgot_ty.ty_adt_def() {
|
||||||
Some(def) => def.has_dtor(),
|
Some(def) => def.has_dtor(),
|
||||||
_ => false
|
_ => false,
|
||||||
} {
|
} {
|
||||||
span_lint(cx, MEM_FORGET, e.span, "usage of mem::forget on Drop type");
|
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,
|
explicit_self.span,
|
||||||
"methods called `new` usually return `Self`");
|
"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::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::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::Any, &hir::Return(ref ty)) if ty.node != hir::TyTup(vec![].into()) => true,
|
||||||
(&OutType::Ref, &hir::Return(ref ty)) => {
|
(&OutType::Ref, &hir::Return(ref ty)) => matches!(ty.node, hir::TyRptr(_, _)),
|
||||||
matches!(ty.node, hir::TyRptr(_, _))
|
|
||||||
}
|
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,10 +34,7 @@ impl LateLintPass for MutMut {
|
||||||
|
|
||||||
if let ExprAddrOf(MutMutable, ref e) = expr.node {
|
if let ExprAddrOf(MutMutable, ref e) = expr.node {
|
||||||
if let ExprAddrOf(MutMutable, _) = e.node {
|
if let ExprAddrOf(MutMutable, _) = e.node {
|
||||||
span_lint(cx,
|
span_lint(cx, MUT_MUT, expr.span, "generally you want to avoid `&mut &mut _` if possible");
|
||||||
MUT_MUT,
|
|
||||||
expr.span,
|
|
||||||
"generally you want to avoid `&mut &mut _` if possible");
|
|
||||||
} else {
|
} else {
|
||||||
if let TyRef(_, TypeAndMut { mutbl: MutMutable, .. }) = cx.tcx.expr_ty(e).sty {
|
if let TyRef(_, TypeAndMut { mutbl: MutMutable, .. }) = cx.tcx.expr_ty(e).sty {
|
||||||
span_lint(cx,
|
span_lint(cx,
|
||||||
|
|
|
@ -42,7 +42,8 @@ impl LateLintPass for NeedlessBorrow {
|
||||||
span_lint(cx,
|
span_lint(cx,
|
||||||
NEEDLESS_BORROW,
|
NEEDLESS_BORROW,
|
||||||
e.span,
|
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(..), &ExprUnary(..)) => (),
|
||||||
(&ExprUnary(UnNeg, ref lit), _) => check_mul(cx, e.span, lit, r),
|
(&ExprUnary(UnNeg, ref lit), _) => check_mul(cx, e.span, lit, r),
|
||||||
(_, &ExprUnary(UnNeg, ref lit)) => check_mul(cx, e.span, lit, l),
|
(_, &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
|
// can't be implemented by default
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if decl.inputs.is_empty() && name.as_str() == "new" &&
|
if decl.inputs.is_empty() && name.as_str() == "new" && cx.access_levels.is_reachable(id) {
|
||||||
cx.access_levels.is_reachable(id) {
|
let self_ty = cx.tcx
|
||||||
let self_ty = cx.tcx.lookup_item_type(cx.tcx.map.local_def_id(
|
.lookup_item_type(cx.tcx.map.local_def_id(cx.tcx.map.get_parent(id)))
|
||||||
cx.tcx.map.get_parent(id))).ty;
|
.ty;
|
||||||
if_let_chain!{[
|
if_let_chain!{[
|
||||||
self_ty.walk_shallow().next().is_none(), // implements_trait does not work with generics
|
self_ty.walk_shallow().next().is_none(), // implements_trait does not work with generics
|
||||||
let Some(ret_ty) = return_ty(cx, id),
|
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() {
|
for field in adt_def.all_fields() {
|
||||||
let f_ty = field.ty(cx.tcx, substs);
|
let f_ty = field.ty(cx.tcx, substs);
|
||||||
if !implements_trait(cx, f_ty, default_trait_id, Vec::new()) {
|
if !implements_trait(cx, f_ty, default_trait_id, Vec::new()) {
|
||||||
return false
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
true
|
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_::ExprTupField(ref inner, _) |
|
||||||
Expr_::ExprAddrOf(_, ref inner) |
|
Expr_::ExprAddrOf(_, ref inner) |
|
||||||
Expr_::ExprBox(ref inner) => reduce_expression(cx, inner).or_else(|| Some(vec![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) => {
|
Expr_::ExprCall(ref callee, ref args) => {
|
||||||
match cx.tcx.def_map.borrow().get(&callee.id).map(PathResolution::full_def) {
|
match cx.tcx.def_map.borrow().get(&callee.id).map(PathResolution::full_def) {
|
||||||
Some(Def::Struct(..)) |
|
Some(Def::Struct(..)) |
|
||||||
|
@ -140,11 +142,13 @@ fn reduce_expression<'a>(cx: &LateContext, expr: &'a Expr) -> Option<Vec<&'a Exp
|
||||||
}
|
}
|
||||||
Expr_::ExprBlock(ref block) => {
|
Expr_::ExprBlock(ref block) => {
|
||||||
if block.stmts.is_empty() {
|
if block.stmts.is_empty() {
|
||||||
block.expr.as_ref().and_then(|e| match block.rules {
|
block.expr.as_ref().and_then(|e| {
|
||||||
BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) => None,
|
match block.rules {
|
||||||
BlockCheckMode::DefaultBlock => Some(vec![&**e]),
|
BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) => None,
|
||||||
// in case of compiler-inserted signaling blocks
|
BlockCheckMode::DefaultBlock => Some(vec![&**e]),
|
||||||
_ => reduce_expression(cx, e),
|
// in case of compiler-inserted signaling blocks
|
||||||
|
_ => reduce_expression(cx, e),
|
||||||
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
None
|
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) {
|
fn visit_pat(&mut self, pat: &'v Pat) {
|
||||||
match pat.node {
|
match pat.node {
|
||||||
PatKind::Ident(_, id, _) => self.check_name(id.span, id.node.name),
|
PatKind::Ident(_, id, _) => self.check_name(id.span, id.node.name),
|
||||||
PatKind::Struct(_, ref fields, _) => for field in fields {
|
PatKind::Struct(_, ref fields, _) => {
|
||||||
if !field.node.is_shorthand {
|
for field in fields {
|
||||||
self.visit_pat(&field.node.pat);
|
if !field.node.is_shorthand {
|
||||||
|
self.visit_pat(&field.node.pat);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
_ => walk_pat(self, pat),
|
_ => walk_pat(self, pat),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -193,15 +195,15 @@ impl<'a, 'b, 'c> SimilarNamesNameVisitor<'a, 'b, 'c> {
|
||||||
span,
|
span,
|
||||||
"binding's name is too similar to existing binding",
|
"binding's name is too similar to existing binding",
|
||||||
|diag| {
|
|diag| {
|
||||||
diag.span_note(existing_name.span, "existing binding defined here");
|
diag.span_note(existing_name.span, "existing binding defined here");
|
||||||
if let Some(split) = split_at {
|
if let Some(split) = split_at {
|
||||||
diag.span_help(span,
|
diag.span_help(span,
|
||||||
&format!("separate the discriminating character by an \
|
&format!("separate the discriminating character by an \
|
||||||
underscore like: `{}_{}`",
|
underscore like: `{}_{}`",
|
||||||
&interned_name[..split],
|
&interned_name[..split],
|
||||||
&interned_name[split..]));
|
&interned_name[split..]));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.0.names.push(ExistingName {
|
self.0.names.push(ExistingName {
|
||||||
|
|
|
@ -125,7 +125,7 @@ impl LateLintPass for RegexPass {
|
||||||
fn str_span(base: Span, s: &str, c: usize) -> Span {
|
fn str_span(base: Span, s: &str, c: usize) -> Span {
|
||||||
let mut si = s.char_indices().skip(c);
|
let mut si = s.char_indices().skip(c);
|
||||||
|
|
||||||
match (si.next(), si.next()) {
|
match (si.next(), si.next()) {
|
||||||
(Some((l, _)), Some((h, _))) => {
|
(Some((l, _)), Some((h, _))) => {
|
||||||
Span {
|
Span {
|
||||||
lo: base.lo + BytePos(l as u32),
|
lo: base.lo + BytePos(l as u32),
|
||||||
|
@ -193,7 +193,9 @@ fn check_regex(cx: &LateContext, expr: &Expr, utf8: bool) {
|
||||||
match builder.parse(r) {
|
match builder.parse(r) {
|
||||||
Ok(r) => {
|
Ok(r) => {
|
||||||
if let Some(repl) = is_trivial_regex(&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",
|
"trivial regex",
|
||||||
&format!("consider using {}", repl));
|
&format!("consider using {}", repl));
|
||||||
}
|
}
|
||||||
|
@ -211,7 +213,9 @@ fn check_regex(cx: &LateContext, expr: &Expr, utf8: bool) {
|
||||||
match builder.parse(&r) {
|
match builder.parse(&r) {
|
||||||
Ok(r) => {
|
Ok(r) => {
|
||||||
if let Some(repl) = is_trivial_regex(&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",
|
"trivial regex",
|
||||||
&format!("consider using {}", repl));
|
&format!("consider using {}", repl));
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ impl LateLintPass for UnsafeNameRemoval {
|
||||||
*name,
|
*name,
|
||||||
cx, &item.span
|
cx, &item.span
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
ViewPath_::ViewPathList(_, ref path_list_items) => {
|
ViewPath_::ViewPathList(_, ref path_list_items) => {
|
||||||
for path_list_item in path_list_items.iter() {
|
for path_list_item in path_list_items.iter() {
|
||||||
let plid = path_list_item.node;
|
let plid = path_list_item.node;
|
||||||
|
@ -53,7 +53,7 @@ impl LateLintPass for UnsafeNameRemoval {
|
||||||
unsafe_to_safe_check(name, rename, cx, &item.span);
|
unsafe_to_safe_check(name, rename, cx, &item.span);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
ViewPath_::ViewPathGlob(_) => {}
|
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 old_str = old_name.as_str();
|
||||||
let new_str = new_name.as_str();
|
let new_str = new_name.as_str();
|
||||||
if contains_unsafe(&old_str) && !contains_unsafe(&new_str) {
|
if contains_unsafe(&old_str) && !contains_unsafe(&new_str) {
|
||||||
span_lint(
|
span_lint(cx,
|
||||||
cx,
|
UNSAFE_REMOVED_FROM_NAME,
|
||||||
UNSAFE_REMOVED_FROM_NAME,
|
*span,
|
||||||
*span,
|
&format!(
|
||||||
&format!(
|
|
||||||
"removed \"unsafe\" from the name of `{}` in use as `{}`",
|
"removed \"unsafe\" from the name of `{}` in use as `{}`",
|
||||||
old_str,
|
old_str,
|
||||||
new_str
|
new_str
|
||||||
|
|
|
@ -64,10 +64,12 @@ impl LateLintPass for UnusedLabel {
|
||||||
impl<'v> Visitor<'v> for UnusedLabelVisitor {
|
impl<'v> Visitor<'v> for UnusedLabelVisitor {
|
||||||
fn visit_expr(&mut self, expr: &hir::Expr) {
|
fn visit_expr(&mut self, expr: &hir::Expr) {
|
||||||
match expr.node {
|
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());
|
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);
|
self.labels.insert(label.node.as_str(), expr.span);
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
|
|
|
@ -50,13 +50,19 @@ pub enum Error {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<io::Error> for 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 {
|
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 {
|
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> {
|
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)) => {
|
(&PatKind::QPath(ref ls, ref lp), &PatKind::QPath(ref rs, ref rp)) => {
|
||||||
self.eq_qself(ls, rs) && self.eq_path(lp, 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)) => {
|
(&PatKind::Range(ref ls, ref le), &PatKind::Range(ref rs, ref re)) => {
|
||||||
self.eq_expr(ls, rs) && self.eq_expr(le, 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 {
|
let mut apb = AbsolutePathBuffer { names: vec![] };
|
||||||
names: vec![],
|
|
||||||
};
|
|
||||||
|
|
||||||
cx.tcx.push_item_path(&mut apb, def_id);
|
cx.tcx.push_item_path(&mut apb, def_id);
|
||||||
|
|
||||||
|
@ -763,7 +761,8 @@ pub fn unsugar_range(expr: &Expr) -> Option<UnsugaredRange> {
|
||||||
end: None,
|
end: None,
|
||||||
limits: RangeLimits::HalfOpen,
|
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 {
|
Some(UnsugaredRange {
|
||||||
start: get_field("start", fields),
|
start: get_field("start", fields),
|
||||||
end: get_field("end", 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());
|
registry.args_hidden = Some(Vec::new());
|
||||||
clippy_lints::register_plugins(&mut registry);
|
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 sess = &state.session;
|
||||||
let mut ls = sess.lint_store.borrow_mut();
|
let mut ls = sess.lint_store.borrow_mut();
|
||||||
for pass in early_lint_passes {
|
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 toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN"));
|
||||||
let sys_root = match (home, toolchain) {
|
let sys_root = match (home, toolchain) {
|
||||||
(Some(home), Some(toolchain)) => format!("{}/toolchains/{}", home, toolchain),
|
(Some(home), Some(toolchain)) => format!("{}/toolchains/{}", home, toolchain),
|
||||||
_ => option_env!("SYSROOT").map(|s| s.to_owned())
|
_ => {
|
||||||
.or(Command::new("rustc").arg("--print")
|
option_env!("SYSROOT")
|
||||||
.arg("sysroot")
|
.map(|s| s.to_owned())
|
||||||
.output().ok()
|
.or(Command::new("rustc")
|
||||||
.and_then(|out| String::from_utf8(out.stdout).ok())
|
.arg("--print")
|
||||||
.map(|s| s.trim().to_owned())
|
.arg("sysroot")
|
||||||
)
|
.output()
|
||||||
.expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust"),
|
.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) {
|
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>
|
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()];
|
let mut args = vec!["rustc".to_owned()];
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,10 @@ struct Test {
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
use Baz::*;
|
use Baz::*;
|
||||||
let x = Test { t: Some(0), b: One };
|
let x = Test {
|
||||||
|
t: Some(0),
|
||||||
|
b: One,
|
||||||
|
};
|
||||||
|
|
||||||
match x {
|
match x {
|
||||||
Test { t: Some(_), b: One } => unreachable!(),
|
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");
|
let cfg_mode = mode.parse().ok().expect("Invalid mode");
|
||||||
config.target_rustcflags = Some("-L target/debug/ -L target/debug/deps".to_owned());
|
config.target_rustcflags = Some("-L target/debug/ -L target/debug/deps".to_owned());
|
||||||
if let Ok(name) = var::<&str>("TESTNAME") {
|
if let Ok(name) = var::<&str>("TESTNAME") {
|
||||||
let s : String = name.to_owned();
|
let s: String = name.to_owned();
|
||||||
config.filter = Some(s)
|
config.filter = Some(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,15 +16,18 @@ use syntax::parse::token::InternedString;
|
||||||
use syntax::ptr::P;
|
use syntax::ptr::P;
|
||||||
|
|
||||||
fn spanned<T>(t: T) -> Spanned<T> {
|
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 {
|
fn expr(n: Expr_) -> Expr {
|
||||||
Expr{
|
Expr {
|
||||||
id: 1,
|
id: 1,
|
||||||
node: n,
|
node: n,
|
||||||
span: COMMAND_LINE_SP,
|
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))
|
assert_eq!(Some(expect), constant_simple(expr))
|
||||||
}
|
}
|
||||||
|
|
||||||
const TRUE : Constant = Constant::Bool(true);
|
const TRUE: Constant = Constant::Bool(true);
|
||||||
const FALSE : Constant = Constant::Bool(false);
|
const FALSE: Constant = Constant::Bool(false);
|
||||||
const ZERO : Constant = Constant::Int(ConstInt::Infer(0));
|
const ZERO: Constant = Constant::Int(ConstInt::Infer(0));
|
||||||
const ONE : Constant = Constant::Int(ConstInt::Infer(1));
|
const ONE: Constant = Constant::Int(ConstInt::Infer(1));
|
||||||
const TWO : Constant = Constant::Int(ConstInt::Infer(2));
|
const TWO: Constant = Constant::Int(ConstInt::Infer(2));
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_lit() {
|
fn test_lit() {
|
||||||
check(TRUE, &lit(LitKind::Bool(true)));
|
check(TRUE, &lit(LitKind::Bool(true)));
|
||||||
check(FALSE, &lit(LitKind::Bool(false)));
|
check(FALSE, &lit(LitKind::Bool(false)));
|
||||||
check(ZERO, &lit(LitKind::Int(0, LitIntType::Unsuffixed)));
|
check(ZERO, &lit(LitKind::Int(0, LitIntType::Unsuffixed)));
|
||||||
check(Constant::Str("cool!".into(), StrStyle::Cooked), &lit(LitKind::Str(
|
check(Constant::Str("cool!".into(), StrStyle::Cooked),
|
||||||
InternedString::new("cool!"), StrStyle::Cooked)));
|
&lit(LitKind::Str(InternedString::new("cool!"), StrStyle::Cooked)));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -30,11 +30,7 @@ fn dogfood() {
|
||||||
|
|
||||||
config.mode = cfg_mode;
|
config.mode = cfg_mode;
|
||||||
|
|
||||||
let files = [
|
let files = ["src/main.rs", "src/lib.rs", "clippy_lints/src/lib.rs"];
|
||||||
"src/main.rs",
|
|
||||||
"src/lib.rs",
|
|
||||||
"clippy_lints/src/lib.rs",
|
|
||||||
];
|
|
||||||
|
|
||||||
for file in &files {
|
for file in &files {
|
||||||
let paths = TestPaths {
|
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 clippy::matches::overlapping;
|
||||||
use syntax::codemap::DUMMY_SP;
|
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::<u8>(&[]));
|
||||||
assert_eq!(None, overlapping(&[sp(1, 4)]));
|
assert_eq!(None, overlapping(&[sp(1, 4)]));
|
||||||
|
|
|
@ -12,5 +12,5 @@ struct MacroAttributesTest {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn macro_attributes_test() {
|
fn macro_attributes_test() {
|
||||||
let _ = MacroAttributesTest{_foo: 0};
|
let _ = MacroAttributesTest { _foo: 0 };
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue