rustfmt all the things

This commit is contained in:
mcarton 2016-04-14 20:14:03 +02:00
parent cd12a2369a
commit a878916ad5
41 changed files with 375 additions and 275 deletions

View file

@ -78,17 +78,16 @@ 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.map(|start| let start = range.start
eval_const_expr_partial(cx.tcx, start, ExprTypeChecked, None)).map(|v| v.ok()); .map(|start| eval_const_expr_partial(cx.tcx, start, ExprTypeChecked, None))
let end = range.end.map(|end| .map(|v| v.ok());
eval_const_expr_partial(cx.tcx, end, ExprTypeChecked, None)).map(|v| v.ok()); let end = range.end
.map(|end| eval_const_expr_partial(cx.tcx, end, ExprTypeChecked, None))
.map(|v| v.ok());
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 {
utils::span_lint(cx, utils::span_lint(cx, OUT_OF_BOUNDS_INDEXING, e.span, "range is out of bounds");
OUT_OF_BOUNDS_INDEXING,
e.span,
"range is out of bounds");
} }
return; return;
} }
@ -111,11 +110,9 @@ impl LateLintPass for ArrayIndexing {
} }
/// Returns an option containing a tuple with the start and end (exclusive) of the range. /// Returns an option containing a tuple with the start and end (exclusive) of the range.
fn to_const_range(start: Option<Option<ConstVal>>, fn to_const_range(start: Option<Option<ConstVal>>, end: Option<Option<ConstVal>>, limits: RangeLimits,
end: Option<Option<ConstVal>>,
limits: RangeLimits,
array_size: ConstInt) array_size: ConstInt)
-> Option<(ConstInt, ConstInt)> { -> Option<(ConstInt, ConstInt)> {
let start = match start { let start = match start {
Some(Some(ConstVal::Integral(x))) => x, Some(Some(ConstVal::Integral(x))) => x,
Some(_) => return None, Some(_) => return None,
@ -131,7 +128,7 @@ fn to_const_range(start: Option<Option<ConstVal>>,
} }
} }
Some(_) => return None, Some(_) => return None,
None => array_size None => array_size,
}; };
Some((start, end)) Some((start, end))

View file

@ -115,7 +115,8 @@ fn is_relevant_block(block: &Block) -> bool {
for stmt in &block.stmts { for stmt in &block.stmts {
match stmt.node { match stmt.node {
StmtDecl(_, _) => return true, StmtDecl(_, _) => return true,
StmtExpr(ref expr, _) | StmtSemi(ref expr, _) => { StmtExpr(ref expr, _) |
StmtSemi(ref expr, _) => {
return is_relevant_expr(expr); return is_relevant_expr(expr);
} }
} }

View file

@ -264,7 +264,7 @@ fn fetch_int_literal(cx: &LateContext, lit: &Expr) -> Option<u64> {
// borrowing. // borrowing.
let def_map = cx.tcx.def_map.borrow(); let def_map = cx.tcx.def_map.borrow();
match def_map.get(&lit.id) { match def_map.get(&lit.id) {
Some(&PathResolution { base_def: Def::Const(def_id), ..}) => Some(def_id), Some(&PathResolution { base_def: Def::Const(def_id), .. }) => Some(def_id),
_ => None, _ => None,
} }
} }

View file

@ -49,7 +49,7 @@ struct NonminimalBoolVisitor<'a, 'tcx: 'a>(&'a LateContext<'a, 'tcx>);
use quine_mc_cluskey::Bool; use quine_mc_cluskey::Bool;
struct Hir2Qmm<'a, 'tcx: 'a, 'v> { struct Hir2Qmm<'a, 'tcx: 'a, 'v> {
terminals: Vec<&'v Expr>, terminals: Vec<&'v Expr>,
cx: &'a LateContext<'a, 'tcx> cx: &'a LateContext<'a, 'tcx>,
} }
impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> {
@ -75,17 +75,17 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> {
match binop.node { match binop.node {
BiOr => return Ok(Bool::Or(self.extract(BiOr, &[lhs, rhs], Vec::new())?)), BiOr => return Ok(Bool::Or(self.extract(BiOr, &[lhs, rhs], Vec::new())?)),
BiAnd => return Ok(Bool::And(self.extract(BiAnd, &[lhs, rhs], Vec::new())?)), BiAnd => return Ok(Bool::And(self.extract(BiAnd, &[lhs, rhs], Vec::new())?)),
_ => {}, _ => (),
} }
}, }
ExprLit(ref lit) => { ExprLit(ref lit) => {
match lit.node { match lit.node {
LitKind::Bool(true) => return Ok(Bool::True), LitKind::Bool(true) => return Ok(Bool::True),
LitKind::Bool(false) => return Ok(Bool::False), LitKind::Bool(false) => return Ok(Bool::False),
_ => {}, _ => (),
} }
}, }
_ => {}, _ => (),
} }
} }
for (n, expr) in self.terminals.iter().enumerate() { for (n, expr) in self.terminals.iter().enumerate() {
@ -95,11 +95,13 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> {
} }
let negated = match e.node { let negated = match e.node {
ExprBinary(binop, ref lhs, ref rhs) => { ExprBinary(binop, ref lhs, ref rhs) => {
let mk_expr = |op| Expr { let mk_expr = |op| {
id: DUMMY_NODE_ID, Expr {
span: DUMMY_SP, id: DUMMY_NODE_ID,
attrs: None, span: DUMMY_SP,
node: ExprBinary(dummy_spanned(op), lhs.clone(), rhs.clone()), attrs: None,
node: ExprBinary(dummy_spanned(op), lhs.clone(), rhs.clone()),
}
}; };
match binop.node { match binop.node {
BiEq => mk_expr(BiNe), BiEq => mk_expr(BiNe),
@ -110,7 +112,7 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> {
BiLe => mk_expr(BiGt), BiLe => mk_expr(BiGt),
_ => continue, _ => continue,
} }
}, }
_ => continue, _ => continue,
}; };
if SpanlessEq::new(self.cx).ignore_fn().eq_expr(&negated, expr) { if SpanlessEq::new(self.cx).ignore_fn().eq_expr(&negated, expr) {
@ -137,17 +139,17 @@ fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String {
True => { True => {
s.push_str("true"); s.push_str("true");
s s
}, }
False => { False => {
s.push_str("false"); s.push_str("false");
s s
}, }
Not(ref inner) => { Not(ref inner) => {
match **inner { match **inner {
And(_) | Or(_) => { And(_) | Or(_) => {
s.push('!'); s.push('!');
recurse(true, cx, inner, terminals, s) recurse(true, cx, inner, terminals, s)
}, }
Term(n) => { Term(n) => {
if let ExprBinary(binop, ref lhs, ref rhs) = terminals[n as usize].node { if let ExprBinary(binop, ref lhs, ref rhs) = terminals[n as usize].node {
let op = match binop.node { let op = match binop.node {
@ -159,8 +161,8 @@ fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String {
BiGe => " < ", BiGe => " < ",
_ => { _ => {
s.push('!'); s.push('!');
return recurse(true, cx, inner, terminals, s) return recurse(true, cx, inner, terminals, s);
}, }
}; };
s.push_str(&snip(lhs)); s.push_str(&snip(lhs));
s.push_str(op); s.push_str(op);
@ -170,13 +172,13 @@ fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String {
s.push('!'); s.push('!');
recurse(false, cx, inner, terminals, s) recurse(false, cx, inner, terminals, s)
} }
}, }
_ => { _ => {
s.push('!'); s.push('!');
recurse(false, cx, inner, terminals, s) recurse(false, cx, inner, terminals, s)
}, }
} }
}, }
And(ref v) => { And(ref v) => {
if brackets { if brackets {
s.push('('); s.push('(');
@ -198,7 +200,7 @@ fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String {
s.push(')'); s.push(')');
} }
s s
}, }
Or(ref v) => { Or(ref v) => {
if brackets { if brackets {
s.push('('); s.push('(');
@ -212,7 +214,7 @@ fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String {
s.push(')'); s.push(')');
} }
s s
}, }
Term(n) => { Term(n) => {
if brackets { if brackets {
if let ExprBinary(..) = terminals[n as usize].node { if let ExprBinary(..) = terminals[n as usize].node {
@ -243,13 +245,13 @@ fn simple_negate(b: Bool) -> Bool {
*el = simple_negate(::std::mem::replace(el, True)); *el = simple_negate(::std::mem::replace(el, True));
} }
Or(v) Or(v)
}, }
Or(mut v) => { Or(mut v) => {
for el in &mut v { for el in &mut v {
*el = simple_negate(::std::mem::replace(el, True)); *el = simple_negate(::std::mem::replace(el, True));
} }
And(v) And(v)
}, }
Not(inner) => *inner, Not(inner) => *inner,
} }
} }
@ -271,13 +273,13 @@ fn terminal_stats(b: &Bool) -> Stats {
_ => stats.negations += 1, _ => stats.negations += 1,
} }
recurse(inner, stats); recurse(inner, stats);
}, }
And(ref v) | Or(ref v) => { And(ref v) | Or(ref v) => {
stats.ops += v.len() - 1; stats.ops += v.len() - 1;
for inner in v { for inner in v {
recurse(inner, stats); recurse(inner, stats);
} }
}, }
Term(n) => stats.terminals[n as usize] += 1, Term(n) => stats.terminals[n as usize] += 1,
} }
} }
@ -306,7 +308,7 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> {
let mut simplified = expr.simplify(); let mut simplified = expr.simplify();
for simple in Bool::Not(Box::new(expr.clone())).simplify() { for simple in Bool::Not(Box::new(expr.clone())).simplify() {
match simple { match simple {
Bool::Not(_) | Bool::True | Bool::False => {}, Bool::Not(_) | Bool::True | Bool::False => {}
_ => simplified.push(Bool::Not(Box::new(simple.clone()))), _ => simplified.push(Bool::Not(Box::new(simple.clone()))),
} }
let simple_negated = simple_negate(simple); let simple_negated = simple_negate(simple);
@ -325,28 +327,43 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> {
continue 'simplified; continue 'simplified;
} }
if stats.terminals[i] != 0 && simplified_stats.terminals[i] == 0 { if stats.terminals[i] != 0 && simplified_stats.terminals[i] == 0 {
span_lint_and_then(self.0, LOGIC_BUG, e.span, "this boolean expression contains a logic bug", |db| { span_lint_and_then(self.0,
db.span_help(h2q.terminals[i].span, "this expression can be optimized out by applying boolean operations to the outer expression"); LOGIC_BUG,
db.span_suggestion(e.span, "it would look like the following", suggest(self.0, suggestion, &h2q.terminals)); e.span,
}); "this boolean expression contains a logic bug",
|db| {
db.span_help(h2q.terminals[i].span,
"this expression can be optimized out by applying \
boolean operations to the outer expression");
db.span_suggestion(e.span,
"it would look like the following",
suggest(self.0, suggestion, &h2q.terminals));
});
// 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.ops == simplified_stats.ops) || (stats.negations > simplified_stats.negations &&
(stats.ops > simplified_stats.ops && stats.negations == simplified_stats.negations); stats.ops == simplified_stats.ops) ||
(stats.ops > simplified_stats.ops && stats.negations == simplified_stats.negations);
} }
if improvement { if improvement {
improvements.push(suggestion); improvements.push(suggestion);
} }
} }
if !improvements.is_empty() { if !improvements.is_empty() {
span_lint_and_then(self.0, NONMINIMAL_BOOL, e.span, "this boolean expression can be simplified", |db| { span_lint_and_then(self.0,
for suggestion in &improvements { NONMINIMAL_BOOL,
db.span_suggestion(e.span, "try", suggest(self.0, suggestion, &h2q.terminals)); e.span,
} "this boolean expression can be simplified",
}); |db| {
for suggestion in &improvements {
db.span_suggestion(e.span,
"try",
suggest(self.0, suggestion, &h2q.terminals));
}
});
} }
} }
} }
@ -354,7 +371,9 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> {
impl<'a, 'v, 'tcx> Visitor<'v> for NonminimalBoolVisitor<'a, 'tcx> { impl<'a, 'v, 'tcx> Visitor<'v> for NonminimalBoolVisitor<'a, 'tcx> {
fn visit_expr(&mut self, e: &'v Expr) { fn visit_expr(&mut self, e: &'v Expr) {
if in_macro(self.0, e.span) { return } if in_macro(self.0, e.span) {
return;
}
match e.node { match e.node {
ExprBinary(binop, _, _) if binop.node == BiOr || binop.node == BiAnd => self.bool_expr(e), ExprBinary(binop, _, _) if binop.node == BiOr || binop.node == BiAnd => self.bool_expr(e),
ExprUnary(UnNot, ref inner) => { ExprUnary(UnNot, ref inner) => {
@ -363,7 +382,7 @@ impl<'a, 'v, 'tcx> Visitor<'v> for NonminimalBoolVisitor<'a, 'tcx> {
} else { } else {
walk_expr(self, e); walk_expr(self, e);
} }
}, }
_ => walk_expr(self, e), _ => walk_expr(self, e),
} }
} }

View file

@ -70,7 +70,7 @@ fn check_if(cx: &LateContext, e: &Expr) {
db.span_suggestion(block.span, "try", snippet_block(cx, else_.span, "..").into_owned()); db.span_suggestion(block.span, "try", snippet_block(cx, else_.span, "..").into_owned());
}); });
}} }}
} else if let Some(&Expr{ node: ExprIf(ref check_inner, ref content, None), span: sp, ..}) = } else if let Some(&Expr { node: ExprIf(ref check_inner, ref content, None), span: sp, .. }) =
single_stmt_of_block(then) { single_stmt_of_block(then) {
if e.span.expn_id != sp.expn_id { if e.span.expn_id != sp.expn_id {
return; return;
@ -89,7 +89,7 @@ fn check_if(cx: &LateContext, e: &Expr) {
fn requires_brackets(e: &Expr) -> bool { fn requires_brackets(e: &Expr) -> bool {
match e.node { match e.node {
ExprBinary(Spanned {node: n, ..}, _, _) if n == BiEq => false, ExprBinary(Spanned { node: n, .. }, _, _) if n == BiEq => false,
_ => true, _ => true,
} }
} }

View file

@ -85,7 +85,9 @@ impl PartialEq for Constant {
(&Constant::Str(ref ls, ref l_sty), &Constant::Str(ref rs, ref r_sty)) => ls == rs && l_sty == r_sty, (&Constant::Str(ref ls, ref l_sty), &Constant::Str(ref rs, ref r_sty)) => ls == rs && l_sty == r_sty,
(&Constant::Binary(ref l), &Constant::Binary(ref r)) => l == r, (&Constant::Binary(ref l), &Constant::Binary(ref r)) => l == r,
(&Constant::Char(l), &Constant::Char(r)) => l == r, (&Constant::Char(l), &Constant::Char(r)) => l == r,
(&Constant::Int(l), &Constant::Int(r)) => l.is_negative() == r.is_negative() && l.to_u64_unchecked() == r.to_u64_unchecked(), (&Constant::Int(l), &Constant::Int(r)) => {
l.is_negative() == r.is_negative() && l.to_u64_unchecked() == r.to_u64_unchecked()
}
(&Constant::Float(ref ls, _), &Constant::Float(ref rs, _)) => { (&Constant::Float(ref ls, _), &Constant::Float(ref rs, _)) => {
// we want `Fw32 == FwAny` and `FwAny == Fw64`, by transitivity we must have // we want `Fw32 == FwAny` and `FwAny == Fw64`, by transitivity we must have
// `Fw32 == Fw64` so dont compare them // `Fw32 == Fw64` so dont compare them
@ -131,7 +133,8 @@ impl Hash for Constant {
Constant::Bool(b) => { Constant::Bool(b) => {
b.hash(state); b.hash(state);
} }
Constant::Vec(ref v) | Constant::Tuple(ref v) => { Constant::Vec(ref v) |
Constant::Tuple(ref v) => {
v.hash(state); v.hash(state);
} }
Constant::Repeat(ref c, l) => { Constant::Repeat(ref c, l) => {
@ -186,12 +189,16 @@ fn lit_to_constant(lit: &LitKind) -> Constant {
LitKind::Int(value, LitIntType::Unsigned(UintTy::U16)) => Constant::Int(ConstInt::U16(value as u16)), LitKind::Int(value, LitIntType::Unsigned(UintTy::U16)) => Constant::Int(ConstInt::U16(value as u16)),
LitKind::Int(value, LitIntType::Unsigned(UintTy::U32)) => Constant::Int(ConstInt::U32(value as u32)), LitKind::Int(value, LitIntType::Unsigned(UintTy::U32)) => Constant::Int(ConstInt::U32(value as u32)),
LitKind::Int(value, LitIntType::Unsigned(UintTy::U64)) => Constant::Int(ConstInt::U64(value as u64)), LitKind::Int(value, LitIntType::Unsigned(UintTy::U64)) => Constant::Int(ConstInt::U64(value as u64)),
LitKind::Int(value, LitIntType::Unsigned(UintTy::Us)) => Constant::Int(ConstInt::Usize(ConstUsize::Us32(value as u32))), LitKind::Int(value, LitIntType::Unsigned(UintTy::Us)) => {
Constant::Int(ConstInt::Usize(ConstUsize::Us32(value as u32)))
}
LitKind::Int(value, LitIntType::Signed(IntTy::I8)) => Constant::Int(ConstInt::I8(value as i8)), LitKind::Int(value, LitIntType::Signed(IntTy::I8)) => Constant::Int(ConstInt::I8(value as i8)),
LitKind::Int(value, LitIntType::Signed(IntTy::I16)) => Constant::Int(ConstInt::I16(value as i16)), LitKind::Int(value, LitIntType::Signed(IntTy::I16)) => Constant::Int(ConstInt::I16(value as i16)),
LitKind::Int(value, LitIntType::Signed(IntTy::I32)) => Constant::Int(ConstInt::I32(value as i32)), LitKind::Int(value, LitIntType::Signed(IntTy::I32)) => Constant::Int(ConstInt::I32(value as i32)),
LitKind::Int(value, LitIntType::Signed(IntTy::I64)) => Constant::Int(ConstInt::I64(value as i64)), LitKind::Int(value, LitIntType::Signed(IntTy::I64)) => Constant::Int(ConstInt::I64(value as i64)),
LitKind::Int(value, LitIntType::Signed(IntTy::Is)) => Constant::Int(ConstInt::Isize(ConstIsize::Is32(value as i32))), LitKind::Int(value, LitIntType::Signed(IntTy::Is)) => {
Constant::Int(ConstInt::Isize(ConstIsize::Is32(value as i32)))
}
LitKind::Float(ref is, ty) => Constant::Float(is.to_string(), ty.into()), LitKind::Float(ref is, ty) => Constant::Float(is.to_string(), ty.into()),
LitKind::FloatUnsuffixed(ref is) => Constant::Float(is.to_string(), FloatWidth::Any), LitKind::FloatUnsuffixed(ref is) => Constant::Float(is.to_string(), FloatWidth::Any),
LitKind::Bool(b) => Constant::Bool(b), LitKind::Bool(b) => Constant::Bool(b),
@ -285,7 +292,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> {
fn fetch_path(&mut self, e: &Expr) -> Option<Constant> { fn fetch_path(&mut self, e: &Expr) -> Option<Constant> {
if let Some(lcx) = self.lcx { if let Some(lcx) = self.lcx {
let mut maybe_id = None; let mut maybe_id = None;
if let Some(&PathResolution { base_def: Def::Const(id), ..}) = lcx.tcx.def_map.borrow().get(&e.id) { if let Some(&PathResolution { base_def: Def::Const(id), .. }) = lcx.tcx.def_map.borrow().get(&e.id) {
maybe_id = Some(id); maybe_id = Some(id);
} }
// separate if lets to avoid double borrowing the def_map // separate if lets to avoid double borrowing the def_map
@ -324,7 +331,11 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> {
} }
fn binop(&mut self, op: BinOp, left: &Expr, right: &Expr) -> Option<Constant> { fn binop(&mut self, op: BinOp, left: &Expr, right: &Expr) -> Option<Constant> {
let l = if let Some(l) = self.expr(left) { l } else { return None; }; let l = if let Some(l) = self.expr(left) {
l
} else {
return None;
};
let r = self.expr(right); let r = self.expr(right);
match (op.node, l, r) { match (op.node, l, r) {
(BiAdd, Constant::Int(l), Some(Constant::Int(r))) => (l + r).ok().map(Constant::Int), (BiAdd, Constant::Int(l), Some(Constant::Int(r))) => (l + r).ok().map(Constant::Int),

View file

@ -71,7 +71,7 @@ impl LateLintPass for CopyAndPaste {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
if !in_macro(cx, expr.span) { if !in_macro(cx, expr.span) {
// skip ifs directly in else, it will be checked in the parent if // skip ifs directly in else, it will be checked in the parent if
if let Some(&Expr{node: ExprIf(_, _, Some(ref else_expr)), ..}) = get_parent_expr(cx, expr) { if let Some(&Expr { node: ExprIf(_, _, Some(ref else_expr)), .. }) = get_parent_expr(cx, expr) {
if else_expr.id == expr.id { if else_expr.id == expr.id {
return; return;
} }
@ -185,7 +185,8 @@ fn if_sequence(mut expr: &Expr) -> (SmallVector<&Expr>, SmallVector<&Block>) {
fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap<InternedString, ty::Ty<'tcx>> { fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap<InternedString, ty::Ty<'tcx>> {
fn bindings_impl<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat, map: &mut HashMap<InternedString, ty::Ty<'tcx>>) { fn bindings_impl<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat, map: &mut HashMap<InternedString, ty::Ty<'tcx>>) {
match pat.node { match pat.node {
PatKind::Box(ref pat) | PatKind::Ref(ref pat, _) => bindings_impl(cx, pat, map), PatKind::Box(ref pat) |
PatKind::Ref(ref pat, _) => bindings_impl(cx, pat, map),
PatKind::TupleStruct(_, Some(ref pats)) => { PatKind::TupleStruct(_, Some(ref pats)) => {
for pat in pats { for pat in pats {
bindings_impl(cx, pat, map); bindings_impl(cx, pat, map);

View file

@ -60,12 +60,7 @@ impl CyclomaticComplexity {
tcx: &cx.tcx, tcx: &cx.tcx,
}; };
helper.visit_block(block); helper.visit_block(block);
let CCHelper { let CCHelper { match_arms, divergence, short_circuits, .. } = helper;
match_arms,
divergence,
short_circuits,
..
} = helper;
if cc + divergence < match_arms + short_circuits { if cc + divergence < match_arms + short_circuits {
report_cc_bug(cx, cc, match_arms, divergence, short_circuits, span); report_cc_bug(cx, cc, match_arms, divergence, short_circuits, span);
@ -132,7 +127,8 @@ impl<'a, 'b, 'tcx> Visitor<'a> for CCHelper<'b, 'tcx> {
walk_expr(self, e); walk_expr(self, e);
let ty = self.tcx.node_id_to_type(callee.id); let ty = self.tcx.node_id_to_type(callee.id);
match ty.sty { match ty.sty {
ty::TyFnDef(_, _, ty) | ty::TyFnPtr(ty) if ty.sig.skip_binder().output.diverges() => { ty::TyFnDef(_, _, ty) |
ty::TyFnPtr(ty) if ty.sig.skip_binder().output.diverges() => {
self.divergence += 1; self.divergence += 1;
} }
_ => (), _ => (),
@ -143,7 +139,7 @@ impl<'a, 'b, 'tcx> Visitor<'a> for CCHelper<'b, 'tcx> {
walk_expr(self, e); walk_expr(self, e);
match op.node { match op.node {
BiAnd | BiOr => self.short_circuits += 1, BiAnd | BiOr => self.short_circuits += 1,
_ => {}, _ => (),
} }
} }
_ => walk_expr(self, e), _ => walk_expr(self, e),
@ -156,10 +152,10 @@ fn report_cc_bug(_: &LateContext, cc: u64, narms: u64, div: u64, shorts: u64, sp
span_bug!(span, span_bug!(span,
"Clippy encountered a bug calculating cyclomatic complexity: cc = {}, arms = {}, \ "Clippy encountered a bug calculating cyclomatic complexity: cc = {}, arms = {}, \
div = {}, shorts = {}. Please file a bug report.", div = {}, shorts = {}. Please file a bug report.",
cc, cc,
narms, narms,
div, div,
shorts); shorts);
} }
#[cfg(not(feature="debugging"))] #[cfg(not(feature="debugging"))]
fn report_cc_bug(cx: &LateContext, cc: u64, narms: u64, div: u64, shorts: u64, span: Span) { fn report_cc_bug(cx: &LateContext, cc: u64, narms: u64, div: u64, shorts: u64, span: Span) {

View file

@ -142,10 +142,10 @@ pub fn check_doc(cx: &EarlyContext, valid_idents: &[String], doc: &str, span: Sp
} }
'`' => { '`' => {
current_word_begin = jump_to!(chars, '`', len); current_word_begin = jump_to!(chars, '`', len);
}, }
'[' => { '[' => {
let end = jump_to!(chars, ']', len); let end = jump_to!(chars, ']', len);
let link_text = &doc[current_word_begin+1..end]; let link_text = &doc[current_word_begin + 1..end];
match chars.peek() { match chars.peek() {
Some(&(_, c)) => { Some(&(_, c)) => {
@ -199,7 +199,7 @@ fn check_word(cx: &EarlyContext, valid_idents: &[String], word: &str, span: Span
} }
let s = if s.ends_with('s') { let s = if s.ends_with('s') {
&s[..s.len()-1] &s[..s.len() - 1]
} else { } else {
s s
}; };
@ -223,6 +223,9 @@ fn check_word(cx: &EarlyContext, valid_idents: &[String], word: &str, span: Span
} }
if has_underscore(word) || word.contains("::") || is_camel_case(word) { if has_underscore(word) || word.contains("::") || is_camel_case(word) {
span_lint(cx, DOC_MARKDOWN, span, &format!("you should put `{}` between ticks in the documentation", word)); span_lint(cx,
DOC_MARKDOWN,
span,
&format!("you should put `{}` between ticks in the documentation", word));
} }
} }

View file

@ -47,7 +47,7 @@ impl LateLintPass for HashMapLint {
// in case of `if !m.contains_key(&k) { m.insert(k, v); }` // in case of `if !m.contains_key(&k) { m.insert(k, v); }`
// we can give a better error message // we can give a better error message
let sole_expr = else_block.is_none() && let sole_expr = else_block.is_none() &&
((then_block.expr.is_some() as usize) + then_block.stmts.len() == 1); ((then_block.expr.is_some() as usize) + then_block.stmts.len() == 1);
let mut visitor = InsertVisitor { let mut visitor = InsertVisitor {
cx: cx, cx: cx,

View file

@ -54,7 +54,7 @@ impl EnumGlobUse {
let child = cx.sess().cstore.item_children(def.def_id()); let child = cx.sess().cstore.item_children(def.def_id());
if let Some(child) = child.first() { if let Some(child) = child.first() {
if let DefLike::DlDef(Def::Variant(..)) = child.def { if let DefLike::DlDef(Def::Variant(..)) = child.def {
span_lint(cx, ENUM_GLOB_USE, item.span, "don't use glob imports for enum variants"); span_lint(cx, ENUM_GLOB_USE, item.span, "don't use glob imports for enum variants");
} }
} }
} }

View file

@ -60,9 +60,10 @@ fn check_closure(cx: &LateContext, expr: &Expr) {
let fn_ty = cx.tcx.expr_ty(caller); let fn_ty = cx.tcx.expr_ty(caller);
match fn_ty.sty { match fn_ty.sty {
// Is it an unsafe function? They don't implement the closure traits // Is it an unsafe function? They don't implement the closure traits
ty::TyFnDef(_, _, fn_ty) | ty::TyFnPtr(fn_ty) => { ty::TyFnDef(_, _, fn_ty) |
ty::TyFnPtr(fn_ty) => {
if fn_ty.unsafety == Unsafety::Unsafe || if fn_ty.unsafety == Unsafety::Unsafe ||
fn_ty.sig.skip_binder().output == ty::FnOutput::FnDiverging { fn_ty.sig.skip_binder().output == ty::FnOutput::FnDiverging {
return; return;
} }
} }

View file

@ -31,9 +31,7 @@ pub struct Functions {
impl Functions { impl Functions {
pub fn new(threshold: u64) -> Functions { pub fn new(threshold: u64) -> Functions {
Functions { Functions { threshold: threshold }
threshold: threshold
}
} }
} }
@ -49,7 +47,8 @@ impl LateLintPass for Functions {
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)) {
match item.node { match item.node {
hir::ItemImpl(_, _, _, Some(_), _, _) | hir::ItemDefaultImpl(..) => return, hir::ItemImpl(_, _, _, Some(_), _, _) |
hir::ItemDefaultImpl(..) => return,
_ => (), _ => (),
} }
} }
@ -68,7 +67,9 @@ impl Functions {
fn check_arg_number(&self, cx: &LateContext, decl: &hir::FnDecl, span: Span) { fn check_arg_number(&self, cx: &LateContext, decl: &hir::FnDecl, span: Span) {
let args = decl.inputs.len() as u64; let args = decl.inputs.len() as u64;
if args > self.threshold { if args > self.threshold {
span_lint(cx, TOO_MANY_ARGUMENTS, span, span_lint(cx,
TOO_MANY_ARGUMENTS,
span,
&format!("this function has to many arguments ({}/{})", args, self.threshold)); &format!("this function has to many arguments ({}/{})", args, self.threshold));
} }
} }

View file

@ -37,15 +37,15 @@ impl EarlyLintPass for IfNotElse {
item.span, item.span,
"Unnecessary boolean `not` operation", "Unnecessary boolean `not` operation",
"remove the `!` and swap the blocks of the if/else"); "remove the `!` and swap the blocks of the if/else");
}, }
ExprKind::Binary(ref kind, _, _) if kind.node == BinOpKind::Ne => { ExprKind::Binary(ref kind, _, _) if kind.node == BinOpKind::Ne => {
span_help_and_lint(cx, span_help_and_lint(cx,
IF_NOT_ELSE, IF_NOT_ELSE,
item.span, item.span,
"Unnecessary `!=` operation", "Unnecessary `!=` operation",
"change to `==` and swap the blocks of the if/else"); "change to `==` and swap the blocks of the if/else");
}, }
_ => {}, _ => (),
} }
} }
} }

View file

@ -64,7 +64,7 @@ impl LateLintPass for LenZero {
return; return;
} }
if let ExprBinary(Spanned{node: cmp, ..}, ref left, ref right) = expr.node { if let ExprBinary(Spanned { node: cmp, .. }, ref left, ref right) = expr.node {
match cmp { match cmp {
BiEq => check_cmp(cx, expr.span, left, right, ""), BiEq => check_cmp(cx, expr.span, left, right, ""),
BiGt | BiNe => check_cmp(cx, expr.span, left, right, "!"), BiGt | BiNe => check_cmp(cx, expr.span, left, right, "!"),
@ -155,7 +155,7 @@ fn check_cmp(cx: &LateContext, span: Span, left: &Expr, right: &Expr, op: &str)
} }
fn check_len_zero(cx: &LateContext, span: Span, name: &Name, args: &[P<Expr>], lit: &Lit, op: &str) { fn check_len_zero(cx: &LateContext, span: Span, name: &Name, args: &[P<Expr>], lit: &Lit, op: &str) {
if let Spanned{node: LitKind::Int(0, _), ..} = *lit { if let Spanned { node: LitKind::Int(0, _), .. } = *lit {
if name.as_str() == "len" && args.len() == 1 && has_is_empty(cx, &args[0]) { if name.as_str() == "len" && args.len() == 1 && has_is_empty(cx, &args[0]) {
span_lint_and_then(cx, LEN_ZERO, span, "length comparison to zero", |db| { span_lint_and_then(cx, LEN_ZERO, span, "length comparison to zero", |db| {
db.span_suggestion(span, db.span_suggestion(span,
@ -199,7 +199,8 @@ fn has_is_empty(cx: &LateContext, expr: &Expr) -> bool {
.map_or(false, |ids| ids.iter().any(|i| is_is_empty(cx, i))) .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::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::TyEnum(ref id, _) |
ty::TyStruct(ref id, _) => has_is_empty_impl(cx, &id.did),
ty::TyArray(..) | ty::TyStr => true, ty::TyArray(..) | ty::TyStr => true,
_ => false, _ => false,
} }

View file

@ -127,7 +127,7 @@ fn could_use_elision<'a, T: Iterator<Item = &'a Lifetime>>(cx: &LateContext, fun
match slf.node { match slf.node {
SelfRegion(ref opt_lt, _, _) => input_visitor.record(opt_lt), SelfRegion(ref opt_lt, _, _) => input_visitor.record(opt_lt),
SelfExplicit(ref ty, _) => walk_ty(&mut input_visitor, ty), SelfExplicit(ref ty, _) => walk_ty(&mut input_visitor, ty),
_ => {} _ => (),
} }
} }
// extract lifetimes in input argument types // extract lifetimes in input argument types
@ -243,7 +243,8 @@ impl<'v, 't> RefVisitor<'v, 't> {
if params.lifetimes.is_empty() { if params.lifetimes.is_empty() {
if let Some(def) = self.cx.tcx.def_map.borrow().get(&ty.id).map(|r| r.full_def()) { if let Some(def) = self.cx.tcx.def_map.borrow().get(&ty.id).map(|r| r.full_def()) {
match def { match def {
Def::TyAlias(def_id) | Def::Struct(def_id) => { Def::TyAlias(def_id) |
Def::Struct(def_id) => {
let type_scheme = self.cx.tcx.lookup_item_type(def_id); let type_scheme = self.cx.tcx.lookup_item_type(def_id);
for _ in type_scheme.generics.regions.as_slice() { for _ in type_scheme.generics.regions.as_slice() {
self.record(&None); self.record(&None);
@ -255,7 +256,7 @@ impl<'v, 't> RefVisitor<'v, 't> {
self.record(&None); self.record(&None);
} }
} }
_ => {} _ => (),
} }
} }
} }
@ -277,7 +278,7 @@ impl<'v, 't> Visitor<'v> for RefVisitor<'v, 't> {
TyPath(_, ref path) => { TyPath(_, ref path) => {
self.collect_anonymous_lifetimes(path, ty); self.collect_anonymous_lifetimes(path, ty);
} }
_ => {} _ => (),
} }
walk_ty(self, ty); walk_ty(self, ty);
} }
@ -353,7 +354,7 @@ fn report_extra_lifetimes(cx: &LateContext, func: &FnDecl, generics: &Generics,
match slf.node { match slf.node {
SelfRegion(Some(ref lt), _, _) => checker.visit_lifetime(lt), SelfRegion(Some(ref lt), _, _) => checker.visit_lifetime(lt),
SelfExplicit(ref t, _) => walk_ty(&mut checker, t), SelfExplicit(ref t, _) => walk_ty(&mut checker, t),
_ => {} _ => (),
} }
} }

View file

@ -14,8 +14,8 @@ use std::collections::HashMap;
use syntax::ast; use syntax::ast;
use utils::{snippet, span_lint, get_parent_expr, match_trait_method, match_type, in_external_macro, use utils::{snippet, span_lint, get_parent_expr, match_trait_method, match_type, in_external_macro,
span_help_and_lint, is_integer_literal, get_enclosing_block, span_lint_and_then, span_help_and_lint, is_integer_literal, get_enclosing_block, span_lint_and_then, unsugar_range,
unsugar_range, walk_ptrs_ty, recover_for_loop}; walk_ptrs_ty, recover_for_loop};
use utils::paths; use utils::paths;
use utils::UnsugaredRange; use utils::UnsugaredRange;
@ -247,7 +247,8 @@ impl LateLintPass for LoopsPass {
if let ExprMatch(ref matchexpr, ref arms, ref source) = inner.node { if let ExprMatch(ref matchexpr, ref arms, ref source) = inner.node {
// ensure "if let" compatible match structure // ensure "if let" compatible match structure
match *source { match *source {
MatchSource::Normal | MatchSource::IfLetDesugar{..} => { MatchSource::Normal |
MatchSource::IfLetDesugar { .. } => {
if arms.len() == 2 && arms[0].pats.len() == 1 && arms[0].guard.is_none() && if arms.len() == 2 && arms[0].pats.len() == 1 && arms[0].guard.is_none() &&
arms[1].pats.len() == 1 && arms[1].guard.is_none() && arms[1].pats.len() == 1 && arms[1].guard.is_none() &&
is_break_expr(&arms[1].body) { is_break_expr(&arms[1].body) {
@ -779,7 +780,8 @@ fn extract_first_expr(block: &Block) -> Option<&Expr> {
Some(ref expr) => Some(expr), Some(ref expr) => Some(expr),
None if !block.stmts.is_empty() => { None if !block.stmts.is_empty() => {
match block.stmts[0].node { match block.stmts[0].node {
StmtExpr(ref expr, _) | StmtSemi(ref expr, _) => Some(expr), StmtExpr(ref expr, _) |
StmtSemi(ref expr, _) => Some(expr),
_ => None, _ => None,
} }
} }

View file

@ -252,19 +252,20 @@ fn check_match_bool(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) {
if let Some((ref true_expr, ref false_expr)) = exprs { if let Some((ref true_expr, ref false_expr)) = exprs {
match (is_unit_expr(true_expr), is_unit_expr(false_expr)) { match (is_unit_expr(true_expr), is_unit_expr(false_expr)) {
(false, false) => (false, false) => {
Some(format!("if {} {} else {}", Some(format!("if {} {} else {}",
snippet(cx, ex.span, "b"), snippet(cx, ex.span, "b"),
expr_block(cx, true_expr, None, ".."), expr_block(cx, true_expr, None, ".."),
expr_block(cx, false_expr, None, ".."))), expr_block(cx, false_expr, None, "..")))
(false, true) => }
Some(format!("if {} {}", (false, true) => {
snippet(cx, ex.span, "b"), Some(format!("if {} {}", snippet(cx, ex.span, "b"), expr_block(cx, true_expr, None, "..")))
expr_block(cx, true_expr, None, ".."))), }
(true, false) => (true, false) => {
Some(format!("try\nif !{} {}", Some(format!("try\nif !{} {}",
snippet(cx, ex.span, "b"), snippet(cx, ex.span, "b"),
expr_block(cx, false_expr, None, ".."))), expr_block(cx, false_expr, None, "..")))
}
(true, true) => None, (true, true) => None,
} }
} else { } else {
@ -312,9 +313,7 @@ fn check_match_ref_pats(cx: &LateContext, ex: &Expr, arms: &[Arm], source: Match
expr.span, expr.span,
"you don't need to add `&` to both the expression and the patterns", "you don't need to add `&` to both the expression and the patterns",
|db| { |db| {
db.span_suggestion(expr.span, db.span_suggestion(expr.span, "try", template);
"try",
template);
}); });
} else { } else {
let template = match_template(cx, expr.span, source, "*", ex); let template = match_template(cx, expr.span, source, "*", ex);
@ -324,7 +323,8 @@ fn check_match_ref_pats(cx: &LateContext, ex: &Expr, arms: &[Arm], source: Match
"you don't need to add `&` to all patterns", "you don't need to add `&` to all patterns",
|db| { |db| {
db.span_suggestion(expr.span, db.span_suggestion(expr.span,
"instead of prefixing all patterns with `&`, you can dereference the expression", "instead of prefixing all patterns with `&`, you can \
dereference the expression",
template); template);
}); });
} }
@ -373,17 +373,18 @@ type TypedRanges = Vec<SpannedRange<ConstInt>>;
/// Get all `Int` ranges or all `Uint` ranges. Mixed types are an error anyway and other types than /// Get all `Int` ranges or all `Uint` ranges. Mixed types are an error anyway and other types than
/// `Uint` and `Int` probably don't make sense. /// `Uint` and `Int` probably don't make sense.
fn type_ranges(ranges: &[SpannedRange<ConstVal>]) -> TypedRanges { fn type_ranges(ranges: &[SpannedRange<ConstVal>]) -> TypedRanges {
ranges.iter().filter_map(|range| { ranges.iter()
if let (ConstVal::Integral(start), ConstVal::Integral(end)) = range.node { .filter_map(|range| {
Some(SpannedRange { if let (ConstVal::Integral(start), ConstVal::Integral(end)) = range.node {
span: range.span, Some(SpannedRange {
node: (start, end), span: range.span,
}) node: (start, end),
} else { })
None } else {
} None
}) }
.collect() })
.collect()
} }
fn is_unit_expr(expr: &Expr) -> bool { fn is_unit_expr(expr: &Expr) -> bool {
@ -416,7 +417,7 @@ fn match_template(cx: &LateContext, span: Span, source: MatchSource, op: &str, e
MatchSource::IfLetDesugar { .. } => format!("if let .. = {}{} {{ .. }}", op, expr_snippet), MatchSource::IfLetDesugar { .. } => format!("if let .. = {}{} {{ .. }}", op, expr_snippet),
MatchSource::WhileLetDesugar => format!("while let .. = {}{} {{ .. }}", op, expr_snippet), MatchSource::WhileLetDesugar => format!("while let .. = {}{} {{ .. }}", op, expr_snippet),
MatchSource::ForLoopDesugar => span_bug!(span, "for loop desugared to match with &-patterns!"), MatchSource::ForLoopDesugar => span_bug!(span, "for loop desugared to match with &-patterns!"),
MatchSource::TryDesugar => span_bug!(span, "`?` operator desugared to match with &-patterns!") MatchSource::TryDesugar => span_bug!(span, "`?` operator desugared to match with &-patterns!"),
} }
} }
@ -432,13 +433,15 @@ pub fn overlapping<T>(ranges: &[SpannedRange<T>]) -> Option<(&SpannedRange<T>, &
impl<'a, T: Copy> Kind<'a, T> { impl<'a, T: Copy> Kind<'a, T> {
fn range(&self) -> &'a SpannedRange<T> { fn range(&self) -> &'a SpannedRange<T> {
match *self { match *self {
Kind::Start(_, r) | Kind::End(_, r) => r, Kind::Start(_, r) |
Kind::End(_, r) => r,
} }
} }
fn value(self) -> T { fn value(self) -> T {
match self { match self {
Kind::Start(t, _) | Kind::End(t, _) => t, Kind::Start(t, _) |
Kind::End(t, _) => t,
} }
} }
} }

View file

@ -436,7 +436,8 @@ impl LateLintPass for MethodsPass {
} }
let ret_ty = return_ty(cx, implitem.id); let ret_ty = return_ty(cx, implitem.id);
if &name.as_str() == &"new" && !ret_ty.map_or(false, |ret_ty| ret_ty.walk().any(|t| same_tys(cx, t, ty, implitem.id))) { if &name.as_str() == &"new" &&
!ret_ty.map_or(false, |ret_ty| ret_ty.walk().any(|t| same_tys(cx, t, ty, implitem.id))) {
span_lint(cx, span_lint(cx,
NEW_RET_NO_SELF, NEW_RET_NO_SELF,
sig.explicit_self.span, sig.explicit_self.span,
@ -946,7 +947,8 @@ impl SelfKind {
(&SelfKind::Ref, &SelfRegion(_, Mutability::MutImmutable, _)) | (&SelfKind::Ref, &SelfRegion(_, Mutability::MutImmutable, _)) |
(&SelfKind::RefMut, &SelfRegion(_, Mutability::MutMutable, _)) | (&SelfKind::RefMut, &SelfRegion(_, Mutability::MutMutable, _)) |
(&SelfKind::No, &SelfStatic) => true, (&SelfKind::No, &SelfStatic) => true,
(&SelfKind::Ref, &SelfValue(_)) | (&SelfKind::RefMut, &SelfValue(_)) => allow_value_for_ref, (&SelfKind::Ref, &SelfValue(_)) |
(&SelfKind::RefMut, &SelfValue(_)) => allow_value_for_ref,
(_, &SelfExplicit(ref ty, _)) => self.matches_explicit_type(ty, allow_value_for_ref), (_, &SelfExplicit(ref ty, _)) => self.matches_explicit_type(ty, allow_value_for_ref),
_ => false, _ => false,
} }

View file

@ -34,7 +34,9 @@ impl LateLintPass for MinMaxPass {
return; return;
} }
match (outer_max, outer_c.partial_cmp(&inner_c)) { match (outer_max, outer_c.partial_cmp(&inner_c)) {
(_, None) | (MinMax::Max, Some(Ordering::Less)) | (MinMax::Min, Some(Ordering::Greater)) => (), (_, None) |
(MinMax::Max, Some(Ordering::Less)) |
(MinMax::Min, Some(Ordering::Greater)) => (),
_ => { _ => {
span_lint(cx, MIN_MAX, expr.span, "this min/max combination leads to constant result"); span_lint(cx, MIN_MAX, expr.span, "this min/max combination leads to constant result");
} }

View file

@ -226,7 +226,7 @@ impl LateLintPass for CmpOwned {
fn check_to_owned(cx: &LateContext, expr: &Expr, other: &Expr, left: bool, op: Span) { fn check_to_owned(cx: &LateContext, expr: &Expr, other: &Expr, left: bool, op: Span) {
let (arg_ty, snip) = match expr.node { let (arg_ty, snip) = match expr.node {
ExprMethodCall(Spanned{node: ref name, ..}, _, ref args) if args.len() == 1 => { ExprMethodCall(Spanned { node: ref name, .. }, _, ref args) if args.len() == 1 => {
if name.as_str() == "to_string" || name.as_str() == "to_owned" && is_str_arg(cx, args) { if name.as_str() == "to_string" || name.as_str() == "to_owned" && is_str_arg(cx, args) {
(cx.tcx.expr_ty(&args[0]), snippet(cx, args[0].span, "..")) (cx.tcx.expr_ty(&args[0]), snippet(cx, args[0].span, ".."))
} else { } else {
@ -309,7 +309,7 @@ impl LintPass for ModuloOne {
impl LateLintPass for ModuloOne { impl LateLintPass for ModuloOne {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
if let ExprBinary(ref cmp, _, ref right) = expr.node { if let ExprBinary(ref cmp, _, ref right) = expr.node {
if let Spanned {node: BinOp_::BiRem, ..} = *cmp { if let Spanned { node: BinOp_::BiRem, .. } = *cmp {
if is_integer_literal(right, 1) { if is_integer_literal(right, 1) {
span_lint(cx, MODULO_ONE, expr.span, "any number modulo 1 will be 0"); span_lint(cx, MODULO_ONE, expr.span, "any number modulo 1 will be 0");
} }
@ -422,7 +422,8 @@ impl LateLintPass for UsedUnderscoreBinding {
fn is_used(cx: &LateContext, expr: &Expr) -> bool { fn is_used(cx: &LateContext, expr: &Expr) -> bool {
if let Some(ref parent) = get_parent_expr(cx, expr) { if let Some(ref parent) = get_parent_expr(cx, expr) {
match parent.node { match parent.node {
ExprAssign(_, ref rhs) | ExprAssignOp(_, _, ref rhs) => **rhs == *expr, ExprAssign(_, ref rhs) |
ExprAssignOp(_, _, ref rhs) => **rhs == *expr,
_ => is_used(cx, &parent), _ => is_used(cx, &parent),
} }
} else { } else {

View file

@ -134,11 +134,11 @@ impl EarlyLintPass for MiscEarly {
expr.span, expr.span,
"Try not to call a closure in the expression where it is declared.", "Try not to call a closure in the expression where it is declared.",
|db| { |db| {
if decl.inputs.is_empty() { if decl.inputs.is_empty() {
let hint = format!("{}", snippet(cx, block.span, "..")); let hint = format!("{}", snippet(cx, block.span, ".."));
db.span_suggestion(expr.span, "Try doing something like: ", hint); db.span_suggestion(expr.span, "Try doing something like: ", hint);
} }
}); });
} }
} }
} }

View file

@ -52,7 +52,7 @@ fn check_expr_mut(cx: &LateContext, expr: &Expr) {
unwrap_addr(expr).map_or((), |e| { unwrap_addr(expr).map_or((), |e| {
unwrap_addr(e).map_or_else(|| { unwrap_addr(e).map_or_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,
MUT_MUT, MUT_MUT,
expr.span, expr.span,
@ -71,7 +71,7 @@ fn check_expr_mut(cx: &LateContext, expr: &Expr) {
fn unwrap_mut(ty: &Ty) -> Option<&Ty> { fn unwrap_mut(ty: &Ty) -> Option<&Ty> {
match ty.node { match ty.node {
TyRptr(_, MutTy{ ty: ref pty, mutbl: MutMutable }) => Some(pty), TyRptr(_, MutTy { ty: ref pty, mutbl: MutMutable }) => Some(pty),
_ => None, _ => None,
} }
} }

View file

@ -47,19 +47,20 @@ impl LateLintPass for UnnecessaryMutPassed {
let method_type = borrowed_table.method_map.get(&method_call).expect("This should never happen."); let method_type = borrowed_table.method_map.get(&method_call).expect("This should never happen.");
check_arguments(cx, &arguments, method_type.ty, &name.node.as_str()) check_arguments(cx, &arguments, method_type.ty, &name.node.as_str())
} }
_ => {} _ => (),
} }
} }
} }
fn check_arguments(cx: &LateContext, arguments: &[P<Expr>], type_definition: &TyS, name: &str) { fn check_arguments(cx: &LateContext, arguments: &[P<Expr>], type_definition: &TyS, name: &str) {
match type_definition.sty { match type_definition.sty {
TypeVariants::TyFnDef(_, _, ref fn_type) | TypeVariants::TyFnPtr(ref fn_type) => { TypeVariants::TyFnDef(_, _, ref fn_type) |
TypeVariants::TyFnPtr(ref fn_type) => {
let parameters = &fn_type.sig.skip_binder().inputs; let parameters = &fn_type.sig.skip_binder().inputs;
for (argument, parameter) in arguments.iter().zip(parameters.iter()) { for (argument, parameter) in arguments.iter().zip(parameters.iter()) {
match parameter.sty { match parameter.sty {
TypeVariants::TyRef(_, TypeAndMut {mutbl: MutImmutable, ..}) | TypeVariants::TyRef(_, TypeAndMut { mutbl: MutImmutable, .. }) |
TypeVariants::TyRawPtr(TypeAndMut {mutbl: MutImmutable, ..}) => { TypeVariants::TyRawPtr(TypeAndMut { mutbl: MutImmutable, .. }) => {
if let ExprAddrOf(MutMutable, _) = argument.node { if let ExprAddrOf(MutMutable, _) = argument.node {
span_lint(cx, span_lint(cx,
UNNECESSARY_MUT_PASSED, UNNECESSARY_MUT_PASSED,
@ -67,7 +68,7 @@ fn check_arguments(cx: &LateContext, arguments: &[P<Expr>], type_definition: &Ty
&format!("The function/method \"{}\" doesn't need a mutable reference", name)); &format!("The function/method \"{}\" doesn't need a mutable reference", name));
} }
} }
_ => {} _ => (),
} }
} }
} }

View file

@ -57,9 +57,10 @@ impl LateLintPass for NeedlessBool {
span_lint_and_then(cx, span_lint_and_then(cx,
NEEDLESS_BOOL, NEEDLESS_BOOL,
e.span, e.span,
"this if-then-else expression returns a bool literal", |db| { "this if-then-else expression returns a bool literal",
db.span_suggestion(e.span, "you can reduce it to", hint); |db| {
}); db.span_suggestion(e.span, "you can reduce it to", hint);
});
}; };
match (fetch_bool_block(then_block), fetch_bool_expr(else_expr)) { match (fetch_bool_block(then_block), fetch_bool_expr(else_expr)) {
(RetBool(true), RetBool(true)) | (RetBool(true), RetBool(true)) |
@ -98,7 +99,7 @@ impl LintPass for BoolComparison {
impl LateLintPass for BoolComparison { impl LateLintPass for BoolComparison {
fn check_expr(&mut self, cx: &LateContext, e: &Expr) { fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
use self::Expression::*; use self::Expression::*;
if let ExprBinary(Spanned{ node: BiEq, .. }, ref left_side, ref right_side) = e.node { if let ExprBinary(Spanned { node: BiEq, .. }, ref left_side, ref right_side) = e.node {
match (fetch_bool_expr(left_side), fetch_bool_expr(right_side)) { match (fetch_bool_expr(left_side), fetch_bool_expr(right_side)) {
(Bool(true), Other) => { (Bool(true), Other) => {
let hint = snippet(cx, right_side.span, "..").into_owned(); let hint = snippet(cx, right_side.span, "..").into_owned();
@ -155,15 +156,17 @@ enum Expression {
fn fetch_bool_block(block: &Block) -> Expression { fn fetch_bool_block(block: &Block) -> Expression {
match (&*block.stmts, block.expr.as_ref()) { match (&*block.stmts, block.expr.as_ref()) {
([], Some(e)) => fetch_bool_expr(&**e), ([], Some(e)) => fetch_bool_expr(&**e),
([ref e], None) => if let StmtSemi(ref e, _) = e.node { ([ref e], None) => {
if let ExprRet(_) = e.node { if let StmtSemi(ref e, _) = e.node {
fetch_bool_expr(&**e) if let ExprRet(_) = e.node {
fetch_bool_expr(&**e)
} else {
Expression::Other
}
} else { } else {
Expression::Other Expression::Other
} }
} else { }
Expression::Other
},
_ => Expression::Other, _ => Expression::Other,
} }
} }
@ -177,11 +180,13 @@ fn fetch_bool_expr(expr: &Expr) -> Expression {
} else { } else {
Expression::Other Expression::Other
} }
}, }
ExprRet(Some(ref expr)) => match fetch_bool_expr(expr) { ExprRet(Some(ref expr)) => {
Expression::Bool(value) => Expression::RetBool(value), match fetch_bool_expr(expr) {
_ => Expression::Other, Expression::Bool(value) => Expression::RetBool(value),
}, _ => Expression::Other,
}
}
_ => Expression::Other, _ => Expression::Other,
} }
} }

View file

@ -52,7 +52,8 @@ fn has_no_effect(cx: &LateContext, expr: &Expr) -> bool {
} }
} }
Expr_::ExprBlock(ref block) => { Expr_::ExprBlock(ref block) => {
block.stmts.is_empty() && if let Some(ref expr) = block.expr { block.stmts.is_empty() &&
if let Some(ref expr) = block.expr {
has_no_effect(cx, expr) has_no_effect(cx, expr)
} else { } else {
false false

View file

@ -45,7 +45,7 @@ struct ExistingName {
interned: InternedString, interned: InternedString,
span: Span, span: Span,
len: usize, len: usize,
whitelist: &'static[&'static str], whitelist: &'static [&'static str],
} }
struct SimilarNamesLocalVisitor<'a, 'b: 'a> { struct SimilarNamesLocalVisitor<'a, 'b: 'a> {
@ -57,6 +57,7 @@ struct SimilarNamesLocalVisitor<'a, 'b: 'a> {
// this list contains lists of names that are allowed to be similar // this list contains lists of names that are allowed to be similar
// the assumption is that no name is ever contained in multiple lists. // the assumption is that no name is ever contained in multiple lists.
#[cfg_attr(rustfmt, rustfmt_skip)]
const WHITELIST: &'static [&'static [&'static str]] = &[ const WHITELIST: &'static [&'static [&'static str]] = &[
&["parsed", "parser"], &["parsed", "parser"],
&["lhs", "rhs"], &["lhs", "rhs"],
@ -75,7 +76,7 @@ impl<'v, 'a, 'b, 'c> visit::Visitor<'v> for SimilarNamesNameVisitor<'a, 'b, 'c>
} }
} }
fn get_whitelist(interned_name: &str) -> Option<&'static[&'static str]> { fn get_whitelist(interned_name: &str) -> Option<&'static [&'static str]> {
for &allow in WHITELIST { for &allow in WHITELIST {
if whitelisted(interned_name, allow) { if whitelisted(interned_name, allow) {
return Some(allow); return Some(allow);
@ -112,8 +113,7 @@ impl<'a, 'b, 'c> SimilarNamesNameVisitor<'a, 'b, 'c> {
span_lint(self.0.cx, span_lint(self.0.cx,
MANY_SINGLE_CHAR_NAMES, MANY_SINGLE_CHAR_NAMES,
span, span,
&format!("{}th binding whose name is just one char", &format!("{}th binding whose name is just one char", self.0.single_char_names.len()));
self.0.single_char_names.len()));
} }
} }
fn check_name(&mut self, span: Span, name: Name) { fn check_name(&mut self, span: Span, name: Name) {
@ -162,7 +162,8 @@ impl<'a, 'b, 'c> SimilarNamesNameVisitor<'a, 'b, 'c> {
} else { } else {
let second_last_i = interned_chars.next_back().expect("we know we have at least three chars"); let second_last_i = interned_chars.next_back().expect("we know we have at least three chars");
let second_last_e = existing_chars.next_back().expect("we know we have at least three chars"); let second_last_e = existing_chars.next_back().expect("we know we have at least three chars");
if !eq_or_numeric(second_last_i, second_last_e) || second_last_i == '_' || !interned_chars.zip(existing_chars).all(|(i, e)| eq_or_numeric(i, e)) { if !eq_or_numeric(second_last_i, second_last_e) || second_last_i == '_' ||
!interned_chars.zip(existing_chars).all(|(i, e)| eq_or_numeric(i, e)) {
// allowed similarity foo_x, foo_y // allowed similarity foo_x, foo_y
// or too many chars differ (foo_x, boo_y) or (foox, booy) // or too many chars differ (foo_x, boo_y) or (foox, booy)
continue; continue;
@ -172,7 +173,8 @@ impl<'a, 'b, 'c> SimilarNamesNameVisitor<'a, 'b, 'c> {
} else { } else {
let second_i = interned_chars.next().expect("we know we have at least two chars"); let second_i = interned_chars.next().expect("we know we have at least two chars");
let second_e = existing_chars.next().expect("we know we have at least two chars"); let second_e = existing_chars.next().expect("we know we have at least two chars");
if !eq_or_numeric(second_i, second_e) || second_i == '_' || !interned_chars.zip(existing_chars).all(|(i, e)| eq_or_numeric(i, e)) { if !eq_or_numeric(second_i, second_e) || second_i == '_' ||
!interned_chars.zip(existing_chars).all(|(i, e)| eq_or_numeric(i, e)) {
// allowed similarity x_foo, y_foo // allowed similarity x_foo, y_foo
// or too many chars differ (x_foo, y_boo) or (xfoo, yboo) // or too many chars differ (x_foo, y_boo) or (xfoo, yboo)
continue; continue;
@ -187,10 +189,11 @@ impl<'a, 'b, 'c> SimilarNamesNameVisitor<'a, 'b, 'c> {
|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, &format!("separate the discriminating character \ diag.span_help(span,
by an underscore like: `{}_{}`", &format!("separate the discriminating character by an \
&interned_name[..split], underscore like: `{}_{}`",
&interned_name[split..])); &interned_name[..split],
&interned_name[split..]));
} }
}); });
return; return;

View file

@ -65,7 +65,7 @@ fn get_open_options(cx: &LateContext, argument: &Expr, options: &mut Vec<(OpenOp
let argument_option = match arguments[1].node { let argument_option = match arguments[1].node {
ExprLit(ref span) => { ExprLit(ref span) => {
if let Spanned {node: LitKind::Bool(lit), ..} = **span { if let Spanned { node: LitKind::Bool(lit), .. } = **span {
if lit { if lit {
Argument::True Argument::True
} else { } else {
@ -96,7 +96,7 @@ fn get_open_options(cx: &LateContext, argument: &Expr, options: &mut Vec<(OpenOp
"write" => { "write" => {
options.push((OpenOption::Write, argument_option)); options.push((OpenOption::Write, argument_option));
} }
_ => {} _ => (),
} }
get_open_options(cx, &arguments[0], options); get_open_options(cx, &arguments[0], options);

View file

@ -1,6 +1,6 @@
use rustc::lint::*; use rustc::lint::*;
use rustc::hir::*; use rustc::hir::*;
use utils::{span_lint}; use utils::span_lint;
/// **What it does:** This lint finds classic underflow / overflow checks. /// **What it does:** This lint finds classic underflow / overflow checks.
/// ///

View file

@ -31,7 +31,7 @@ impl LintPass for Precedence {
impl EarlyLintPass for Precedence { impl EarlyLintPass for Precedence {
fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) { fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) {
if let ExprKind::Binary(Spanned { node: op, ..}, ref left, ref right) = expr.node { if let ExprKind::Binary(Spanned { node: op, .. }, ref left, ref right) = expr.node {
if !is_bit_op(op) { if !is_bit_op(op) {
return; return;
} }
@ -75,7 +75,9 @@ impl EarlyLintPass for Precedence {
if let Some(slf) = args.first() { if let Some(slf) = args.first() {
if let ExprKind::Lit(ref lit) = slf.node { if let ExprKind::Lit(ref lit) = slf.node {
match lit.node { match lit.node {
LitKind::Int(..) | LitKind::Float(..) | LitKind::FloatUnsuffixed(..) => { LitKind::Int(..) |
LitKind::Float(..) |
LitKind::FloatUnsuffixed(..) => {
span_lint(cx, span_lint(cx,
PRECEDENCE, PRECEDENCE,
expr.span, expr.span,
@ -94,7 +96,7 @@ impl EarlyLintPass for Precedence {
fn is_arith_expr(expr: &Expr) -> bool { fn is_arith_expr(expr: &Expr) -> bool {
match expr.node { match expr.node {
ExprKind::Binary(Spanned { node: op, ..}, _, _) => is_arith_op(op), ExprKind::Binary(Spanned { node: op, .. }, _, _) => is_arith_op(op),
_ => false, _ => false,
} }
} }

View file

@ -167,14 +167,14 @@ fn is_trivial_regex(s: &regex_syntax::Expr) -> Option<&'static str> {
match *s { match *s {
Expr::Empty | Expr::StartText | Expr::EndText => Some("the regex is unlikely to be useful as it is"), Expr::Empty | Expr::StartText | Expr::EndText => Some("the regex is unlikely to be useful as it is"),
Expr::Literal {..} => Some("consider using `str::contains`"), Expr::Literal { .. } => Some("consider using `str::contains`"),
Expr::Concat(ref exprs) => { Expr::Concat(ref exprs) => {
match exprs.len() { match exprs.len() {
2 => { 2 => {
match (&exprs[0], &exprs[1]) { match (&exprs[0], &exprs[1]) {
(&Expr::StartText, &Expr::EndText) => Some("consider using `str::is_empty`"), (&Expr::StartText, &Expr::EndText) => Some("consider using `str::is_empty`"),
(&Expr::StartText, &Expr::Literal {..}) => Some("consider using `str::starts_with`"), (&Expr::StartText, &Expr::Literal { .. }) => Some("consider using `str::starts_with`"),
(&Expr::Literal {..}, &Expr::EndText) => Some("consider using `str::ends_with`"), (&Expr::Literal { .. }, &Expr::EndText) => Some("consider using `str::ends_with`"),
_ => None, _ => None,
} }
} }

View file

@ -71,7 +71,7 @@ impl ReturnPass {
self.check_final_expr(cx, &arm.body); self.check_final_expr(cx, &arm.body);
} }
} }
_ => {} _ => (),
} }
} }

View file

@ -77,7 +77,8 @@ fn check_block(cx: &LateContext, block: &Block, bindings: &mut Vec<(Name, Span)>
for stmt in &block.stmts { for stmt in &block.stmts {
match stmt.node { match stmt.node {
StmtDecl(ref decl, _) => check_decl(cx, decl, bindings), StmtDecl(ref decl, _) => check_decl(cx, decl, bindings),
StmtExpr(ref e, _) | StmtSemi(ref e, _) => check_expr(cx, e, bindings), StmtExpr(ref e, _) |
StmtSemi(ref e, _) => check_expr(cx, e, bindings),
} }
} }
if let Some(ref o) = block.expr { if let Some(ref o) = block.expr {
@ -94,7 +95,7 @@ fn check_decl(cx: &LateContext, decl: &Decl, bindings: &mut Vec<(Name, Span)>) {
return; return;
} }
if let DeclLocal(ref local) = decl.node { if let DeclLocal(ref local) = decl.node {
let Local{ ref pat, ref ty, ref init, span, .. } = **local; let Local { ref pat, ref ty, ref init, span, .. } = **local;
if let Some(ref t) = *ty { if let Some(ref t) = *ty {
check_ty(cx, t, bindings) check_ty(cx, t, bindings)
} }
@ -109,7 +110,8 @@ fn check_decl(cx: &LateContext, decl: &Decl, bindings: &mut Vec<(Name, Span)>) {
fn is_binding(cx: &LateContext, pat: &Pat) -> bool { fn is_binding(cx: &LateContext, pat: &Pat) -> bool {
match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) { match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
Some(Def::Variant(..)) | Some(Def::Struct(..)) => false, Some(Def::Variant(..)) |
Some(Def::Struct(..)) => false,
_ => true, _ => true,
} }
} }
@ -251,7 +253,8 @@ fn check_expr(cx: &LateContext, expr: &Expr, bindings: &mut Vec<(Name, Span)>) {
ExprTupField(ref e, _) | ExprTupField(ref e, _) |
ExprAddrOf(_, ref e) | ExprAddrOf(_, ref e) |
ExprBox(ref e) => check_expr(cx, e, bindings), ExprBox(ref e) => check_expr(cx, e, bindings),
ExprBlock(ref block) | ExprLoop(ref block, _) => check_block(cx, block, bindings), ExprBlock(ref block) |
ExprLoop(ref block, _) => check_block(cx, block, bindings),
// ExprCall // ExprCall
// ExprMethodCall // ExprMethodCall
ExprVec(ref v) | ExprTup(ref v) => { ExprVec(ref v) | ExprTup(ref v) => {
@ -297,8 +300,8 @@ fn check_ty(cx: &LateContext, ty: &Ty, bindings: &mut Vec<(Name, Span)>) {
check_ty(cx, fty, bindings); check_ty(cx, fty, bindings);
check_expr(cx, expr, bindings); check_expr(cx, expr, bindings);
} }
TyPtr(MutTy{ ty: ref mty, .. }) | TyPtr(MutTy { ty: ref mty, .. }) |
TyRptr(_, MutTy{ ty: ref mty, .. }) => check_ty(cx, mty, bindings), TyRptr(_, MutTy { ty: ref mty, .. }) => check_ty(cx, mty, bindings),
TyTup(ref tup) => { TyTup(ref tup) => {
for ref t in tup { for ref t in tup {
check_ty(cx, t, bindings) check_ty(cx, t, bindings)

View file

@ -74,7 +74,7 @@ impl LintPass for StringAdd {
impl LateLintPass for StringAdd { impl LateLintPass for StringAdd {
fn check_expr(&mut self, cx: &LateContext, e: &Expr) { fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
if let ExprBinary(Spanned{ node: BiAdd, .. }, ref left, _) = e.node { if let ExprBinary(Spanned { node: BiAdd, .. }, ref left, _) = e.node {
if is_string(cx, left) { if is_string(cx, left) {
if let Allow = cx.current_level(STRING_ADD_ASSIGN) { if let Allow = cx.current_level(STRING_ADD_ASSIGN) {
// the string_add_assign is allow, so no duplicates // the string_add_assign is allow, so no duplicates
@ -112,7 +112,7 @@ fn is_string(cx: &LateContext, e: &Expr) -> bool {
fn is_add(cx: &LateContext, src: &Expr, target: &Expr) -> bool { fn is_add(cx: &LateContext, src: &Expr, target: &Expr) -> bool {
match src.node { match src.node {
ExprBinary(Spanned{ node: BiAdd, .. }, ref left, _) => SpanlessEq::new(cx).eq_expr(target, left), ExprBinary(Spanned { node: BiAdd, .. }, ref left, _) => SpanlessEq::new(cx).eq_expr(target, left),
ExprBlock(ref block) => { ExprBlock(ref block) => {
block.stmts.is_empty() && block.expr.as_ref().map_or(false, |expr| is_add(cx, expr, target)) block.stmts.is_empty() && block.expr.as_ref().map_or(false, |expr| is_add(cx, expr, target))
} }
@ -145,8 +145,7 @@ impl LateLintPass for StringLitAsBytes {
e.span, e.span,
"calling `as_bytes()` on a string literal", "calling `as_bytes()` on a string literal",
|db| { |db| {
let sugg = format!("b{}", let sugg = format!("b{}", snippet(cx, args[0].span, r#""foo""#));
snippet(cx, args[0].span, r#""foo""#));
db.span_suggestion(e.span, db.span_suggestion(e.span,
"consider using a byte string literal instead", "consider using a byte string literal instead",
sugg); sugg);

View file

@ -18,8 +18,7 @@ declare_lint! {
fn is_temporary(expr: &Expr) -> bool { fn is_temporary(expr: &Expr) -> bool {
match expr.node { match expr.node {
ExprStruct(..) | ExprStruct(..) | ExprTup(..) => true,
ExprTup(..) => true,
_ => false, _ => false,
} }
} }
@ -37,7 +36,8 @@ impl LateLintPass for TemporaryAssignmentPass {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
if let ExprAssign(ref target, _) = expr.node { if let ExprAssign(ref target, _) = expr.node {
match target.node { match target.node {
ExprField(ref base, _) | ExprTupField(ref base, _) => { ExprField(ref base, _) |
ExprTupField(ref base, _) => {
if is_temporary(base) && !is_adjusted(cx, base) { if is_temporary(base) && !is_adjusted(cx, base) {
span_lint(cx, TEMPORARY_ASSIGNMENT, expr.span, "assignment to temporary"); span_lint(cx, TEMPORARY_ASSIGNMENT, expr.span, "assignment to temporary");
} }

View file

@ -52,11 +52,7 @@ pub struct Transmute;
impl LintPass for Transmute { impl LintPass for Transmute {
fn get_lints(&self) -> LintArray { fn get_lints(&self) -> LintArray {
lint_array! [ lint_array![CROSSPOINTER_TRANSMUTE, TRANSMUTE_PTR_TO_REF, USELESS_TRANSMUTE]
CROSSPOINTER_TRANSMUTE,
TRANSMUTE_PTR_TO_REF,
USELESS_TRANSMUTE
]
} }
} }
@ -79,12 +75,16 @@ impl LateLintPass for Transmute {
span_lint(cx, span_lint(cx,
CROSSPOINTER_TRANSMUTE, CROSSPOINTER_TRANSMUTE,
e.span, e.span,
&format!("transmute from a type (`{}`) to a pointer to that type (`{}`)", from_ty, to_ty)); &format!("transmute from a type (`{}`) to a pointer to that type (`{}`)",
from_ty,
to_ty));
} else if is_ptr_to(from_ty, to_ty) { } else if is_ptr_to(from_ty, to_ty) {
span_lint(cx, span_lint(cx,
CROSSPOINTER_TRANSMUTE, CROSSPOINTER_TRANSMUTE,
e.span, e.span,
&format!("transmute from a type (`{}`) to the type that it points to (`{}`)", from_ty, to_ty)); &format!("transmute from a type (`{}`) to the type that it points to (`{}`)",
from_ty,
to_ty));
} else { } else {
check_ptr_to_ref(cx, from_ty, to_ty, e, &args[0]); check_ptr_to_ref(cx, from_ty, to_ty, e, &args[0]);
} }
@ -102,10 +102,7 @@ fn is_ptr_to(from: ty::Ty, to: ty::Ty) -> bool {
} }
} }
fn check_ptr_to_ref<'tcx>(cx: &LateContext, fn check_ptr_to_ref<'tcx>(cx: &LateContext, from_ty: ty::Ty<'tcx>, to_ty: ty::Ty<'tcx>, e: &Expr, arg: &Expr) {
from_ty: ty::Ty<'tcx>,
to_ty: ty::Ty<'tcx>,
e: &Expr, arg: &Expr) {
if let TyRawPtr(ref from_pty) = from_ty.sty { if let TyRawPtr(ref from_pty) = from_ty.sty {
if let TyRef(_, ref to_rty) = to_ty.sty { if let TyRef(_, ref to_rty) = to_ty.sty {
let mess = format!("transmute from a pointer type (`{}`) to a reference type (`{}`)", let mess = format!("transmute from a pointer type (`{}`) to a reference type (`{}`)",
@ -122,8 +119,7 @@ fn check_ptr_to_ref<'tcx>(cx: &LateContext,
let sugg = if from_pty.ty == to_rty.ty { let sugg = if from_pty.ty == to_rty.ty {
format!("{}{}", deref, arg) format!("{}{}", deref, arg)
} } else {
else {
format!("{}({} as {} {})", deref, arg, cast, to_rty.ty) format!("{}({} as {} {})", deref, arg, cast, to_rty.ty)
}; };

View file

@ -248,7 +248,8 @@ fn int_ty_to_nbits(typ: &ty::TyS) -> usize {
fn is_isize_or_usize(typ: &ty::TyS) -> bool { fn is_isize_or_usize(typ: &ty::TyS) -> bool {
match typ.sty { match typ.sty {
ty::TyInt(IntTy::Is) | ty::TyUint(UintTy::Us) => true, ty::TyInt(IntTy::Is) |
ty::TyUint(UintTy::Us) => true,
_ => false, _ => false,
} }
} }
@ -536,9 +537,7 @@ impl<'v> Visitor<'v> for TypeComplexityVisitor {
fn visit_ty(&mut self, ty: &'v Ty) { fn visit_ty(&mut self, ty: &'v Ty) {
let (add_score, sub_nest) = match ty.node { let (add_score, sub_nest) = match ty.node {
// _, &x and *x have only small overhead; don't mess with nesting level // _, &x and *x have only small overhead; don't mess with nesting level
TyInfer | TyInfer | TyPtr(..) | TyRptr(..) => (1, 0),
TyPtr(..) |
TyRptr(..) => (1, 0),
// the "normal" components of a type: named types, arrays/tuples // the "normal" components of a type: named types, arrays/tuples
TyPath(..) | TyPath(..) |
@ -663,17 +662,17 @@ fn detect_absurd_comparison<'a>(cx: &LateContext, op: BinOp_, lhs: &'a Expr, rhs
Some(match rel { Some(match rel {
Rel::Lt => { Rel::Lt => {
match (lx, rx) { match (lx, rx) {
(Some(l @ Extr { which: Maximum, ..}), _) => (l, AlwaysFalse), // max < x (Some(l @ Extr { which: Maximum, .. }), _) => (l, AlwaysFalse), // max < x
(_, Some(r @ Extr { which: Minimum, ..})) => (r, AlwaysFalse), // x < min (_, Some(r @ Extr { which: Minimum, .. })) => (r, AlwaysFalse), // x < min
_ => return None, _ => return None,
} }
} }
Rel::Le => { Rel::Le => {
match (lx, rx) { match (lx, rx) {
(Some(l @ Extr { which: Minimum, ..}), _) => (l, AlwaysTrue), // min <= x (Some(l @ Extr { which: Minimum, .. }), _) => (l, AlwaysTrue), // min <= x
(Some(l @ Extr { which: Maximum, ..}), _) => (l, InequalityImpossible), //max <= x (Some(l @ Extr { which: Maximum, .. }), _) => (l, InequalityImpossible), //max <= x
(_, Some(r @ Extr { which: Minimum, ..})) => (r, InequalityImpossible), // x <= min (_, Some(r @ Extr { which: Minimum, .. })) => (r, InequalityImpossible), // x <= min
(_, Some(r @ Extr { which: Maximum, ..})) => (r, AlwaysTrue), // x <= max (_, Some(r @ Extr { which: Maximum, .. })) => (r, AlwaysTrue), // x <= max
_ => return None, _ => return None,
} }
} }
@ -702,14 +701,12 @@ fn detect_extreme_expr<'a>(cx: &LateContext, expr: &'a Expr) -> Option<ExtremeEx
let which = match (ty, cv) { let which = match (ty, cv) {
(&ty::TyBool, Bool(false)) | (&ty::TyBool, Bool(false)) |
(&ty::TyInt(IntTy::Is), Integral(Isize(Is32(::std::i32::MIN)))) | (&ty::TyInt(IntTy::Is), Integral(Isize(Is32(::std::i32::MIN)))) |
(&ty::TyInt(IntTy::Is), Integral(Isize(Is64(::std::i64::MIN)))) | (&ty::TyInt(IntTy::Is), Integral(Isize(Is64(::std::i64::MIN)))) |
(&ty::TyInt(IntTy::I8), Integral(I8(::std::i8::MIN))) | (&ty::TyInt(IntTy::I8), Integral(I8(::std::i8::MIN))) |
(&ty::TyInt(IntTy::I16), Integral(I16(::std::i16::MIN))) | (&ty::TyInt(IntTy::I16), Integral(I16(::std::i16::MIN))) |
(&ty::TyInt(IntTy::I32), Integral(I32(::std::i32::MIN))) | (&ty::TyInt(IntTy::I32), Integral(I32(::std::i32::MIN))) |
(&ty::TyInt(IntTy::I64), Integral(I64(::std::i64::MIN))) | (&ty::TyInt(IntTy::I64), Integral(I64(::std::i64::MIN))) |
(&ty::TyUint(UintTy::Us), Integral(Usize(Us32(::std::u32::MIN)))) | (&ty::TyUint(UintTy::Us), Integral(Usize(Us32(::std::u32::MIN)))) |
(&ty::TyUint(UintTy::Us), Integral(Usize(Us64(::std::u64::MIN)))) | (&ty::TyUint(UintTy::Us), Integral(Usize(Us64(::std::u64::MIN)))) |
(&ty::TyUint(UintTy::U8), Integral(U8(::std::u8::MIN))) | (&ty::TyUint(UintTy::U8), Integral(U8(::std::u8::MIN))) |
@ -718,14 +715,12 @@ fn detect_extreme_expr<'a>(cx: &LateContext, expr: &'a Expr) -> Option<ExtremeEx
(&ty::TyUint(UintTy::U64), Integral(U64(::std::u64::MIN))) => Minimum, (&ty::TyUint(UintTy::U64), Integral(U64(::std::u64::MIN))) => Minimum,
(&ty::TyBool, Bool(true)) | (&ty::TyBool, Bool(true)) |
(&ty::TyInt(IntTy::Is), Integral(Isize(Is32(::std::i32::MAX)))) | (&ty::TyInt(IntTy::Is), Integral(Isize(Is32(::std::i32::MAX)))) |
(&ty::TyInt(IntTy::Is), Integral(Isize(Is64(::std::i64::MAX)))) | (&ty::TyInt(IntTy::Is), Integral(Isize(Is64(::std::i64::MAX)))) |
(&ty::TyInt(IntTy::I8), Integral(I8(::std::i8::MAX))) | (&ty::TyInt(IntTy::I8), Integral(I8(::std::i8::MAX))) |
(&ty::TyInt(IntTy::I16), Integral(I16(::std::i16::MAX))) | (&ty::TyInt(IntTy::I16), Integral(I16(::std::i16::MAX))) |
(&ty::TyInt(IntTy::I32), Integral(I32(::std::i32::MAX))) | (&ty::TyInt(IntTy::I32), Integral(I32(::std::i32::MAX))) |
(&ty::TyInt(IntTy::I64), Integral(I64(::std::i64::MAX))) | (&ty::TyInt(IntTy::I64), Integral(I64(::std::i64::MAX))) |
(&ty::TyUint(UintTy::Us), Integral(Usize(Us32(::std::u32::MAX)))) | (&ty::TyUint(UintTy::Us), Integral(Usize(Us32(::std::u32::MAX)))) |
(&ty::TyUint(UintTy::Us), Integral(Usize(Us64(::std::u64::MAX)))) | (&ty::TyUint(UintTy::Us), Integral(Usize(Us64(::std::u64::MAX)))) |
(&ty::TyUint(UintTy::U8), Integral(U8(::std::u8::MAX))) | (&ty::TyUint(UintTy::U8), Integral(U8(::std::u8::MAX))) |
@ -845,22 +840,26 @@ fn numeric_cast_precast_bounds<'a>(cx: &LateContext, expr: &'a Expr) -> Option<(
use syntax::ast::{IntTy, UintTy}; use syntax::ast::{IntTy, UintTy};
use std::*; use std::*;
if let ExprCast(ref cast_exp,_) = expr.node { if let ExprCast(ref cast_exp, _) = expr.node {
match cx.tcx.expr_ty(cast_exp).sty { match cx.tcx.expr_ty(cast_exp).sty {
TyInt(int_ty) => Some(match int_ty { TyInt(int_ty) => {
IntTy::I8 => (FullInt::S(i8::min_value() as i64), FullInt::S(i8::max_value() as i64)), Some(match int_ty {
IntTy::I16 => (FullInt::S(i16::min_value() as i64), FullInt::S(i16::max_value() as i64)), IntTy::I8 => (FullInt::S(i8::min_value() as i64), FullInt::S(i8::max_value() as i64)),
IntTy::I32 => (FullInt::S(i32::min_value() as i64), FullInt::S(i32::max_value() as i64)), IntTy::I16 => (FullInt::S(i16::min_value() as i64), FullInt::S(i16::max_value() as i64)),
IntTy::I64 => (FullInt::S(i64::min_value() as i64), FullInt::S(i64::max_value() as i64)), IntTy::I32 => (FullInt::S(i32::min_value() as i64), FullInt::S(i32::max_value() as i64)),
IntTy::Is => (FullInt::S(isize::min_value() as i64), FullInt::S(isize::max_value() as i64)), IntTy::I64 => (FullInt::S(i64::min_value() as i64), FullInt::S(i64::max_value() as i64)),
}), IntTy::Is => (FullInt::S(isize::min_value() as i64), FullInt::S(isize::max_value() as i64)),
TyUint(uint_ty) => Some(match uint_ty { })
UintTy::U8 => (FullInt::U(u8::min_value() as u64), FullInt::U(u8::max_value() as u64)), }
UintTy::U16 => (FullInt::U(u16::min_value() as u64), FullInt::U(u16::max_value() as u64)), TyUint(uint_ty) => {
UintTy::U32 => (FullInt::U(u32::min_value() as u64), FullInt::U(u32::max_value() as u64)), Some(match uint_ty {
UintTy::U64 => (FullInt::U(u64::min_value() as u64), FullInt::U(u64::max_value() as u64)), UintTy::U8 => (FullInt::U(u8::min_value() as u64), FullInt::U(u8::max_value() as u64)),
UintTy::Us => (FullInt::U(usize::min_value() as u64), FullInt::U(usize::max_value() as u64)), UintTy::U16 => (FullInt::U(u16::min_value() as u64), FullInt::U(u16::max_value() as u64)),
}), UintTy::U32 => (FullInt::U(u32::min_value() as u64), FullInt::U(u32::max_value() as u64)),
UintTy::U64 => (FullInt::U(u64::min_value() as u64), FullInt::U(u64::max_value() as u64)),
UintTy::Us => (FullInt::U(usize::min_value() as u64), FullInt::U(usize::max_value() as u64)),
})
}
_ => None, _ => None,
} }
} else { } else {
@ -885,29 +884,26 @@ fn node_as_const_fullint(cx: &LateContext, expr: &Expr) -> Option<FullInt> {
} else { } else {
None None
} }
}, }
Err(_) => None, Err(_) => None,
} }
} }
fn err_upcast_comparison(cx: &LateContext, span: &Span, expr: &Expr, always: bool) { fn err_upcast_comparison(cx: &LateContext, span: &Span, expr: &Expr, always: bool) {
if let ExprCast(ref cast_val, _) = expr.node { if let ExprCast(ref cast_val, _) = expr.node {
span_lint( span_lint(cx,
cx, INVALID_UPCAST_COMPARISONS,
INVALID_UPCAST_COMPARISONS, *span,
*span, &format!(
&format!(
"because of the numeric bounds on `{}` prior to casting, this expression is always {}", "because of the numeric bounds on `{}` prior to casting, this expression is always {}",
snippet(cx, cast_val.span, "the expression"), snippet(cx, cast_val.span, "the expression"),
if always { "true" } else { "false" }, if always { "true" } else { "false" },
) ));
);
} }
} }
fn upcast_comparison_bounds_err( fn upcast_comparison_bounds_err(cx: &LateContext, span: &Span, rel: comparisons::Rel,
cx: &LateContext, span: &Span, rel: comparisons::Rel, lhs_bounds: Option<(FullInt, FullInt)>, lhs: &Expr, rhs: &Expr, invert: bool) {
lhs_bounds: Option<(FullInt, FullInt)>, lhs: &Expr, rhs: &Expr, invert: bool) {
use utils::comparisons::*; use utils::comparisons::*;
if let Some((lb, ub)) = lhs_bounds { if let Some((lb, ub)) = lhs_bounds {
@ -917,14 +913,38 @@ fn upcast_comparison_bounds_err(
err_upcast_comparison(cx, &span, lhs, rel == Rel::Ne); err_upcast_comparison(cx, &span, lhs, rel == Rel::Ne);
} }
} else if match rel { } else if match rel {
Rel::Lt => if invert { norm_rhs_val < lb } else { ub < norm_rhs_val }, Rel::Lt => {
Rel::Le => if invert { norm_rhs_val <= lb } else { ub <= norm_rhs_val }, if invert {
norm_rhs_val < lb
} else {
ub < norm_rhs_val
}
}
Rel::Le => {
if invert {
norm_rhs_val <= lb
} else {
ub <= norm_rhs_val
}
}
Rel::Eq | Rel::Ne => unreachable!(), Rel::Eq | Rel::Ne => unreachable!(),
} { } {
err_upcast_comparison(cx, &span, lhs, true) err_upcast_comparison(cx, &span, lhs, true)
} else if match rel { } else if match rel {
Rel::Lt => if invert { norm_rhs_val >= ub } else { lb >= norm_rhs_val }, Rel::Lt => {
Rel::Le => if invert { norm_rhs_val > ub } else { lb > norm_rhs_val }, if invert {
norm_rhs_val >= ub
} else {
lb >= norm_rhs_val
}
}
Rel::Le => {
if invert {
norm_rhs_val > ub
} else {
lb > norm_rhs_val
}
}
Rel::Eq | Rel::Ne => unreachable!(), Rel::Eq | Rel::Ne => unreachable!(),
} { } {
err_upcast_comparison(cx, &span, lhs, false) err_upcast_comparison(cx, &span, lhs, false)

View file

@ -8,7 +8,8 @@ use toml;
pub fn conf_file(args: &[ptr::P<ast::MetaItem>]) -> Result<Option<token::InternedString>, (&'static str, codemap::Span)> { pub fn conf_file(args: &[ptr::P<ast::MetaItem>]) -> Result<Option<token::InternedString>, (&'static str, codemap::Span)> {
for arg in args { for arg in args {
match arg.node { match arg.node {
ast::MetaItemKind::Word(ref name) | ast::MetaItemKind::List(ref name, _) => { ast::MetaItemKind::Word(ref name) |
ast::MetaItemKind::List(ref name, _) => {
if name == &"conf_file" { if name == &"conf_file" {
return Err(("`conf_file` must be a named value", arg.span)); return Err(("`conf_file` must be a named value", arg.span));
} }

View file

@ -76,7 +76,9 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
(&ExprBlock(ref l), &ExprBlock(ref r)) => self.eq_block(l, r), (&ExprBlock(ref l), &ExprBlock(ref r)) => self.eq_block(l, r),
(&ExprBinary(l_op, ref ll, ref lr), &ExprBinary(r_op, ref rl, ref rr)) => { (&ExprBinary(l_op, ref ll, ref lr), &ExprBinary(r_op, ref rl, ref rr)) => {
l_op.node == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) || l_op.node == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) ||
swap_binop(l_op.node, ll, lr).map_or(false, |(l_op, ll, lr)| l_op == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr)) swap_binop(l_op.node, ll, lr).map_or(false, |(l_op, ll, lr)| {
l_op == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr)
})
} }
(&ExprBreak(li), &ExprBreak(ri)) => both(&li, &ri, |l, r| l.node.name.as_str() == r.node.name.as_str()), (&ExprBreak(li), &ExprBreak(ri)) => both(&li, &ri, |l, r| l.node.name.as_str() == r.node.name.as_str()),
(&ExprBox(ref l), &ExprBox(ref r)) => self.eq_expr(l, r), (&ExprBox(ref l), &ExprBox(ref r)) => self.eq_expr(l, r),
@ -114,9 +116,8 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
both(l_qself, r_qself, |l, r| self.eq_qself(l, r)) && self.eq_path(l_subpath, r_subpath) both(l_qself, r_qself, |l, r| self.eq_qself(l, r)) && self.eq_path(l_subpath, r_subpath)
} }
(&ExprStruct(ref l_path, ref lf, ref lo), &ExprStruct(ref r_path, ref rf, ref ro)) => { (&ExprStruct(ref l_path, ref lf, ref lo), &ExprStruct(ref r_path, ref rf, ref ro)) => {
self.eq_path(l_path, r_path) && self.eq_path(l_path, r_path) && both(lo, ro, |l, r| self.eq_expr(l, r)) &&
both(lo, ro, |l, r| self.eq_expr(l, r)) && over(lf, rf, |l, r| self.eq_field(l, r))
over(lf, rf, |l, r| self.eq_field(l, r))
} }
(&ExprTup(ref l_tup), &ExprTup(ref r_tup)) => self.eq_exprs(l_tup, r_tup), (&ExprTup(ref l_tup), &ExprTup(ref r_tup)) => self.eq_exprs(l_tup, r_tup),
(&ExprTupField(ref le, li), &ExprTupField(ref re, ri)) => li.node == ri.node && self.eq_expr(le, re), (&ExprTupField(ref le, li), &ExprTupField(ref re, ri)) => li.node == ri.node && self.eq_expr(le, re),

View file

@ -144,7 +144,8 @@ pub fn match_def_path(cx: &LateContext, def_id: DefId, path: &[&str]) -> bool {
/// Check if type is struct or enum type with given def path. /// Check if type is struct or enum type with given def path.
pub fn match_type(cx: &LateContext, ty: ty::Ty, path: &[&str]) -> bool { pub fn match_type(cx: &LateContext, ty: ty::Ty, path: &[&str]) -> bool {
match ty.sty { match ty.sty {
ty::TyEnum(ref adt, _) | ty::TyStruct(ref adt, _) => match_def_path(cx, adt.did, path), ty::TyEnum(ref adt, _) |
ty::TyStruct(ref adt, _) => match_def_path(cx, adt.did, path),
_ => false, _ => false,
} }
} }
@ -304,9 +305,9 @@ pub fn method_chain_args<'a>(expr: &'a Expr, methods: &[&str]) -> Option<Vec<&'a
pub fn get_item_name(cx: &LateContext, expr: &Expr) -> Option<Name> { pub fn get_item_name(cx: &LateContext, expr: &Expr) -> Option<Name> {
let parent_id = cx.tcx.map.get_parent(expr.id); let parent_id = cx.tcx.map.get_parent(expr.id);
match cx.tcx.map.find(parent_id) { match cx.tcx.map.find(parent_id) {
Some(Node::NodeItem(&Item{ ref name, .. })) | Some(Node::NodeItem(&Item { ref name, .. })) |
Some(Node::NodeTraitItem(&TraitItem{ ref name, .. })) | Some(Node::NodeTraitItem(&TraitItem { ref name, .. })) |
Some(Node::NodeImplItem(&ImplItem{ ref name, .. })) => Some(*name), Some(Node::NodeImplItem(&ImplItem { ref name, .. })) => Some(*name),
_ => None, _ => None,
} }
} }
@ -431,7 +432,7 @@ pub fn get_enclosing_block<'c>(cx: &'c LateContext, node: NodeId) -> Option<&'c
if let Some(node) = enclosing_node { if let Some(node) = enclosing_node {
match node { match node {
Node::NodeBlock(ref block) => Some(block), Node::NodeBlock(ref block) => Some(block),
Node::NodeItem(&Item{ node: ItemFn(_, _, _, _, _, ref block), .. }) => Some(block), Node::NodeItem(&Item { node: ItemFn(_, _, _, _, _, ref block), .. }) => Some(block),
_ => None, _ => None,
} }
} else { } else {
@ -517,7 +518,8 @@ pub fn span_lint_and_then<'a, T: LintContext, F>(cx: &'a T, lint: &'static Lint,
/// Return the base type for references and raw pointers. /// Return the base type for references and raw pointers.
pub fn walk_ptrs_ty(ty: ty::Ty) -> ty::Ty { pub fn walk_ptrs_ty(ty: ty::Ty) -> ty::Ty {
match ty.sty { match ty.sty {
ty::TyRef(_, ref tm) | ty::TyRawPtr(ref tm) => walk_ptrs_ty(tm.ty), ty::TyRef(_, ref tm) |
ty::TyRawPtr(ref tm) => walk_ptrs_ty(tm.ty),
_ => ty, _ => ty,
} }
} }
@ -526,7 +528,8 @@ pub fn walk_ptrs_ty(ty: ty::Ty) -> ty::Ty {
pub fn walk_ptrs_ty_depth(ty: ty::Ty) -> (ty::Ty, usize) { pub fn walk_ptrs_ty_depth(ty: ty::Ty) -> (ty::Ty, usize) {
fn inner(ty: ty::Ty, depth: usize) -> (ty::Ty, usize) { fn inner(ty: ty::Ty, depth: usize) -> (ty::Ty, usize) {
match ty.sty { match ty.sty {
ty::TyRef(_, ref tm) | ty::TyRawPtr(ref tm) => inner(tm.ty, depth + 1), ty::TyRef(_, ref tm) |
ty::TyRawPtr(ref tm) => inner(tm.ty, depth + 1),
_ => (ty, depth), _ => (ty, depth),
} }
} }
@ -730,22 +733,46 @@ pub fn unsugar_range(expr: &Expr) -> Option<UnsugaredRange> {
match unwrap_unstable(&expr).node { match unwrap_unstable(&expr).node {
ExprPath(None, ref path) => { ExprPath(None, ref path) => {
if match_path(path, &paths::RANGE_FULL) { if match_path(path, &paths::RANGE_FULL) {
Some(UnsugaredRange { start: None, end: None, limits: RangeLimits::HalfOpen }) Some(UnsugaredRange {
start: None,
end: None,
limits: RangeLimits::HalfOpen,
})
} else { } else {
None None
} }
} }
ExprStruct(ref path, ref fields, None) => { ExprStruct(ref path, ref fields, None) => {
if match_path(path, &paths::RANGE_FROM) { if match_path(path, &paths::RANGE_FROM) {
Some(UnsugaredRange { start: get_field("start", fields), end: None, limits: RangeLimits::HalfOpen }) Some(UnsugaredRange {
start: get_field("start", fields),
end: None,
limits: RangeLimits::HalfOpen,
})
} else if match_path(path, &paths::RANGE_INCLUSIVE_NON_EMPTY) { } else if match_path(path, &paths::RANGE_INCLUSIVE_NON_EMPTY) {
Some(UnsugaredRange { start: get_field("start", fields), end: get_field("end", fields), limits: RangeLimits::Closed }) Some(UnsugaredRange {
start: get_field("start", fields),
end: get_field("end", fields),
limits: RangeLimits::Closed,
})
} else if match_path(path, &paths::RANGE) { } else if match_path(path, &paths::RANGE) {
Some(UnsugaredRange { start: get_field("start", fields), end: get_field("end", fields), limits: RangeLimits::HalfOpen }) Some(UnsugaredRange {
start: get_field("start", fields),
end: get_field("end", fields),
limits: RangeLimits::HalfOpen,
})
} else if match_path(path, &paths::RANGE_TO_INCLUSIVE) { } else if match_path(path, &paths::RANGE_TO_INCLUSIVE) {
Some(UnsugaredRange { start: None, end: get_field("end", fields), limits: RangeLimits::Closed }) Some(UnsugaredRange {
start: None,
end: get_field("end", fields),
limits: RangeLimits::Closed,
})
} else if match_path(path, &paths::RANGE_TO) { } else if match_path(path, &paths::RANGE_TO) {
Some(UnsugaredRange { start: None, end: get_field("end", fields), limits: RangeLimits::HalfOpen }) Some(UnsugaredRange {
start: None,
end: get_field("end", fields),
limits: RangeLimits::HalfOpen,
})
} else { } else {
None None
} }

View file

@ -63,8 +63,7 @@ fn check_vec_macro(cx: &LateContext, expr: &Expr, vec: &Expr) {
}; };
format!("&[{}]", snippet(cx, span, "..")).into() format!("&[{}]", snippet(cx, span, "..")).into()
} } else {
else {
"&[]".into() "&[]".into()
} }
} }