Skip to content

Commit 5a97ba3

Browse files
committed
Update clippy
1 parent 171b6e3 commit 5a97ba3

File tree

138 files changed

+2107
-1147
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

138 files changed

+2107
-1147
lines changed

.travis.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,6 @@ matrix:
8585
allow_failures:
8686
- os: windows
8787
env: CARGO_INCREMENTAL=0 BASE_TESTS=true OS_WINDOWS=true
88-
- os: osx # run base tests on both platforms
89-
env: BASE_TESTS=true
9088
# prevent these jobs with default env vars
9189
exclude:
9290
- os: linux

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -962,6 +962,7 @@ Released 2018-09-13
962962
[`cmp_owned`]: https://rust-lang.github.io/rust-clippy/master/index.html#cmp_owned
963963
[`cognitive_complexity`]: https://rust-lang.github.io/rust-clippy/master/index.html#cognitive_complexity
964964
[`collapsible_if`]: https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_if
965+
[`comparison_chain`]: https://rust-lang.github.io/rust-clippy/master/index.html#comparison_chain
965966
[`copy_iterator`]: https://rust-lang.github.io/rust-clippy/master/index.html#copy_iterator
966967
[`crosspointer_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#crosspointer_transmute
967968
[`dbg_macro`]: https://rust-lang.github.io/rust-clippy/master/index.html#dbg_macro

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code.
88

9-
[There are 316 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
9+
[There are 317 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
1010

1111
We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you:
1212

clippy_lints/src/booleans.rs

Lines changed: 76 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::utils::{
2-
get_trait_def_id, implements_trait, in_macro, match_type, paths, snippet_opt, span_lint_and_then, SpanlessEq,
2+
get_trait_def_id, implements_trait, in_macro, match_type, paths, snippet_opt, span_lint_and_sugg,
3+
span_lint_and_then, SpanlessEq,
34
};
45
use if_chain::if_chain;
56
use rustc::hir::intravisit::*;
@@ -159,46 +160,6 @@ struct SuggestContext<'a, 'tcx, 'v> {
159160
}
160161

161162
impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> {
162-
fn snip(&self, e: &Expr) -> Option<String> {
163-
snippet_opt(self.cx, e.span)
164-
}
165-
166-
fn simplify_not(&self, expr: &Expr) -> Option<String> {
167-
match &expr.node {
168-
ExprKind::Binary(binop, lhs, rhs) => {
169-
if !implements_ord(self.cx, lhs) {
170-
return None;
171-
}
172-
173-
match binop.node {
174-
BinOpKind::Eq => Some(" != "),
175-
BinOpKind::Ne => Some(" == "),
176-
BinOpKind::Lt => Some(" >= "),
177-
BinOpKind::Gt => Some(" <= "),
178-
BinOpKind::Le => Some(" > "),
179-
BinOpKind::Ge => Some(" < "),
180-
_ => None,
181-
}
182-
.and_then(|op| Some(format!("{}{}{}", self.snip(lhs)?, op, self.snip(rhs)?)))
183-
},
184-
ExprKind::MethodCall(path, _, args) if args.len() == 1 => {
185-
let type_of_receiver = self.cx.tables.expr_ty(&args[0]);
186-
if !match_type(self.cx, type_of_receiver, &paths::OPTION)
187-
&& !match_type(self.cx, type_of_receiver, &paths::RESULT)
188-
{
189-
return None;
190-
}
191-
METHODS_WITH_NEGATION
192-
.iter()
193-
.cloned()
194-
.flat_map(|(a, b)| vec![(a, b), (b, a)])
195-
.find(|&(a, _)| a == path.ident.name.as_str())
196-
.and_then(|(_, neg_method)| Some(format!("{}.{}()", self.snip(&args[0])?, neg_method)))
197-
},
198-
_ => None,
199-
}
200-
}
201-
202163
fn recurse(&mut self, suggestion: &Bool) -> Option<()> {
203164
use quine_mc_cluskey::Bool::*;
204165
match suggestion {
@@ -217,12 +178,12 @@ impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> {
217178
},
218179
Term(n) => {
219180
let terminal = self.terminals[n as usize];
220-
if let Some(str) = self.simplify_not(terminal) {
181+
if let Some(str) = simplify_not(self.cx, terminal) {
221182
self.simplified = true;
222183
self.output.push_str(&str)
223184
} else {
224185
self.output.push('!');
225-
let snip = self.snip(terminal)?;
186+
let snip = snippet_opt(self.cx, terminal.span)?;
226187
self.output.push_str(&snip);
227188
}
228189
},
@@ -254,14 +215,55 @@ impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> {
254215
}
255216
},
256217
&Term(n) => {
257-
let snip = self.snip(self.terminals[n as usize])?;
218+
let snip = snippet_opt(self.cx, self.terminals[n as usize].span)?;
258219
self.output.push_str(&snip);
259220
},
260221
}
261222
Some(())
262223
}
263224
}
264225

226+
fn simplify_not(cx: &LateContext<'_, '_>, expr: &Expr) -> Option<String> {
227+
match &expr.node {
228+
ExprKind::Binary(binop, lhs, rhs) => {
229+
if !implements_ord(cx, lhs) {
230+
return None;
231+
}
232+
233+
match binop.node {
234+
BinOpKind::Eq => Some(" != "),
235+
BinOpKind::Ne => Some(" == "),
236+
BinOpKind::Lt => Some(" >= "),
237+
BinOpKind::Gt => Some(" <= "),
238+
BinOpKind::Le => Some(" > "),
239+
BinOpKind::Ge => Some(" < "),
240+
_ => None,
241+
}
242+
.and_then(|op| {
243+
Some(format!(
244+
"{}{}{}",
245+
snippet_opt(cx, lhs.span)?,
246+
op,
247+
snippet_opt(cx, rhs.span)?
248+
))
249+
})
250+
},
251+
ExprKind::MethodCall(path, _, args) if args.len() == 1 => {
252+
let type_of_receiver = cx.tables.expr_ty(&args[0]);
253+
if !match_type(cx, type_of_receiver, &paths::OPTION) && !match_type(cx, type_of_receiver, &paths::RESULT) {
254+
return None;
255+
}
256+
METHODS_WITH_NEGATION
257+
.iter()
258+
.cloned()
259+
.flat_map(|(a, b)| vec![(a, b), (b, a)])
260+
.find(|&(a, _)| a == path.ident.name.as_str())
261+
.and_then(|(_, neg_method)| Some(format!("{}.{}()", snippet_opt(cx, args[0].span)?, neg_method)))
262+
},
263+
_ => None,
264+
}
265+
}
266+
265267
// The boolean part of the return indicates whether some simplifications have been applied.
266268
fn suggest(cx: &LateContext<'_, '_>, suggestion: &Bool, terminals: &[&Expr]) -> (String, bool) {
267269
let mut suggest_context = SuggestContext {
@@ -330,7 +332,7 @@ fn terminal_stats(b: &Bool) -> Stats {
330332
}
331333

332334
impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> {
333-
fn bool_expr(&self, e: &Expr) {
335+
fn bool_expr(&self, e: &'tcx Expr) {
334336
let mut h2q = Hir2Qmm {
335337
terminals: Vec::new(),
336338
cx: self.cx,
@@ -420,10 +422,8 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> {
420422
);
421423
};
422424
if improvements.is_empty() {
423-
let suggest = suggest(self.cx, &expr, &h2q.terminals);
424-
if suggest.1 {
425-
nonminimal_bool_lint(vec![suggest.0])
426-
}
425+
let mut visitor = NotSimplificationVisitor { cx: self.cx };
426+
visitor.visit_expr(e);
427427
} else {
428428
nonminimal_bool_lint(
429429
improvements
@@ -464,3 +464,30 @@ fn implements_ord<'a, 'tcx>(cx: &'a LateContext<'a, 'tcx>, expr: &Expr) -> bool
464464
let ty = cx.tables.expr_ty(expr);
465465
get_trait_def_id(cx, &paths::ORD).map_or(false, |id| implements_trait(cx, ty, id, &[]))
466466
}
467+
468+
struct NotSimplificationVisitor<'a, 'tcx> {
469+
cx: &'a LateContext<'a, 'tcx>,
470+
}
471+
472+
impl<'a, 'tcx> Visitor<'tcx> for NotSimplificationVisitor<'a, 'tcx> {
473+
fn visit_expr(&mut self, expr: &'tcx Expr) {
474+
if let ExprKind::Unary(UnNot, inner) = &expr.node {
475+
if let Some(suggestion) = simplify_not(self.cx, inner) {
476+
span_lint_and_sugg(
477+
self.cx,
478+
NONMINIMAL_BOOL,
479+
expr.span,
480+
"this boolean expression can be simplified",
481+
"try",
482+
suggestion,
483+
Applicability::MachineApplicable,
484+
);
485+
}
486+
}
487+
488+
walk_expr(self, expr);
489+
}
490+
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
491+
NestedVisitorMap::None
492+
}
493+
}

clippy_lints/src/bytecount.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ByteCount {
6262
_ => { return; }
6363
}
6464
};
65-
if ty::Uint(UintTy::U8) != walk_ptrs_ty(cx.tables.expr_ty(needle)).sty {
65+
if ty::Uint(UintTy::U8) != walk_ptrs_ty(cx.tables.expr_ty(needle)).kind {
6666
return;
6767
}
6868
let haystack = if let ExprKind::MethodCall(ref path, _, ref args) =

clippy_lints/src/comparison_chain.rs

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
use crate::utils::{if_sequence, parent_node_is_if_expr, span_help_and_lint, SpanlessEq};
2+
use rustc::hir::*;
3+
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
4+
use rustc::{declare_lint_pass, declare_tool_lint};
5+
6+
declare_clippy_lint! {
7+
/// **What it does:** Checks comparison chains written with `if` that can be
8+
/// rewritten with `match` and `cmp`.
9+
///
10+
/// **Why is this bad?** `if` is not guaranteed to be exhaustive and conditionals can get
11+
/// repetitive
12+
///
13+
/// **Known problems:** None.
14+
///
15+
/// **Example:**
16+
/// ```rust,ignore
17+
/// # fn a() {}
18+
/// # fn b() {}
19+
/// # fn c() {}
20+
/// fn f(x: u8, y: u8) {
21+
/// if x > y {
22+
/// a()
23+
/// } else if x < y {
24+
/// b()
25+
/// } else {
26+
/// c()
27+
/// }
28+
/// }
29+
/// ```
30+
///
31+
/// Could be written:
32+
///
33+
/// ```rust,ignore
34+
/// use std::cmp::Ordering;
35+
/// # fn a() {}
36+
/// # fn b() {}
37+
/// # fn c() {}
38+
/// fn f(x: u8, y: u8) {
39+
/// match x.cmp(&y) {
40+
/// Ordering::Greater => a(),
41+
/// Ordering::Less => b(),
42+
/// Ordering::Equal => c()
43+
/// }
44+
/// }
45+
/// ```
46+
pub COMPARISON_CHAIN,
47+
style,
48+
"`if`s that can be rewritten with `match` and `cmp`"
49+
}
50+
51+
declare_lint_pass!(ComparisonChain => [COMPARISON_CHAIN]);
52+
53+
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ComparisonChain {
54+
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
55+
if expr.span.from_expansion() {
56+
return;
57+
}
58+
59+
// We only care about the top-most `if` in the chain
60+
if parent_node_is_if_expr(expr, cx) {
61+
return;
62+
}
63+
64+
// Check that there exists at least one explicit else condition
65+
let (conds, _) = if_sequence(expr);
66+
if conds.len() < 2 {
67+
return;
68+
}
69+
70+
for cond in conds.windows(2) {
71+
if let (
72+
&ExprKind::Binary(ref kind1, ref lhs1, ref rhs1),
73+
&ExprKind::Binary(ref kind2, ref lhs2, ref rhs2),
74+
) = (&cond[0].node, &cond[1].node)
75+
{
76+
if !kind_is_cmp(kind1.node) || !kind_is_cmp(kind2.node) {
77+
return;
78+
}
79+
80+
// Check that both sets of operands are equal
81+
let mut spanless_eq = SpanlessEq::new(cx);
82+
if (!spanless_eq.eq_expr(lhs1, lhs2) || !spanless_eq.eq_expr(rhs1, rhs2))
83+
&& (!spanless_eq.eq_expr(lhs1, rhs2) || !spanless_eq.eq_expr(rhs1, lhs2))
84+
{
85+
return;
86+
}
87+
} else {
88+
// We only care about comparison chains
89+
return;
90+
}
91+
}
92+
span_help_and_lint(
93+
cx,
94+
COMPARISON_CHAIN,
95+
expr.span,
96+
"`if` chain can be rewritten with `match`",
97+
"Consider rewriting the `if` chain to use `cmp` and `match`.",
98+
)
99+
}
100+
}
101+
102+
fn kind_is_cmp(kind: BinOpKind) -> bool {
103+
match kind {
104+
BinOpKind::Lt | BinOpKind::Gt | BinOpKind::Eq => true,
105+
_ => false,
106+
}
107+
}

0 commit comments

Comments
 (0)