Skip to content

Commit 2670627

Browse files
committed
Update Clippy
1 parent e656531 commit 2670627

27 files changed

+500
-281
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1285,6 +1285,7 @@ Released 2018-09-13
12851285
[`single_char_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_char_pattern
12861286
[`single_match`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match
12871287
[`single_match_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match_else
1288+
[`skip_while_next`]: https://rust-lang.github.io/rust-clippy/master/index.html#skip_while_next
12881289
[`slow_vector_initialization`]: https://rust-lang.github.io/rust-clippy/master/index.html#slow_vector_initialization
12891290
[`str_to_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#str_to_string
12901291
[`string_add`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_add

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 347 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
9+
[There are 348 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_dev/src/stderr_length_check.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use std::io::prelude::*;
77
// The maximum length allowed for stderr files.
88
//
99
// We limit this because small files are easier to deal with than bigger files.
10-
const LIMIT: usize = 275;
10+
const LIMIT: usize = 245;
1111

1212
pub fn check() {
1313
let stderr_files = stderr_files();

clippy_lints/src/assertions_on_constants.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,16 @@ declare_lint_pass!(AssertionsOnConstants => [ASSERTIONS_ON_CONSTANTS]);
3333

3434
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssertionsOnConstants {
3535
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr<'_>) {
36-
let lint_true = || {
36+
let lint_true = |is_debug: bool| {
3737
span_help_and_lint(
3838
cx,
3939
ASSERTIONS_ON_CONSTANTS,
4040
e.span,
41-
"`assert!(true)` will be optimized out by the compiler",
41+
if is_debug {
42+
"`debug_assert!(true)` will be optimized out by the compiler"
43+
} else {
44+
"`assert!(true)` will be optimized out by the compiler"
45+
},
4246
"remove it",
4347
);
4448
};
@@ -70,7 +74,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssertionsOnConstants {
7074
if let Some((Constant::Bool(is_true), _)) = constant(cx, cx.tables, lit);
7175
if is_true;
7276
then {
73-
lint_true();
77+
lint_true(true);
7478
}
7579
};
7680
} else if let Some(assert_span) = is_direct_expn_of(e.span, "assert") {
@@ -81,7 +85,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssertionsOnConstants {
8185
match assert_match {
8286
// matched assert but not message
8387
AssertKind::WithoutMessage(false) => lint_false_without_message(),
84-
AssertKind::WithoutMessage(true) | AssertKind::WithMessage(_, true) => lint_true(),
88+
AssertKind::WithoutMessage(true) | AssertKind::WithMessage(_, true) => lint_true(false),
8589
AssertKind::WithMessage(panic_message, false) => lint_false_with_message(panic_message),
8690
};
8791
}

clippy_lints/src/atomic_ordering.rs

Lines changed: 64 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use rustc_session::{declare_lint_pass, declare_tool_lint};
88

99
declare_clippy_lint! {
1010
/// **What it does:** Checks for usage of invalid atomic
11-
/// ordering in Atomic*::{load, store} calls.
11+
/// ordering in atomic loads/stores and memory fences.
1212
///
1313
/// **Why is this bad?** Using an invalid atomic ordering
1414
/// will cause a panic at run-time.
@@ -17,7 +17,7 @@ declare_clippy_lint! {
1717
///
1818
/// **Example:**
1919
/// ```rust,no_run
20-
/// # use std::sync::atomic::{AtomicBool, Ordering};
20+
/// # use std::sync::atomic::{self, AtomicBool, Ordering};
2121
///
2222
/// let x = AtomicBool::new(true);
2323
///
@@ -26,10 +26,13 @@ declare_clippy_lint! {
2626
///
2727
/// x.store(false, Ordering::Acquire);
2828
/// x.store(false, Ordering::AcqRel);
29+
///
30+
/// atomic::fence(Ordering::Relaxed);
31+
/// atomic::compiler_fence(Ordering::Relaxed);
2932
/// ```
3033
pub INVALID_ATOMIC_ORDERING,
3134
correctness,
32-
"usage of invalid atomic ordering in atomic load/store calls"
35+
"usage of invalid atomic ordering in atomic loads/stores and memory fences"
3336
}
3437

3538
declare_lint_pass!(AtomicOrdering => [INVALID_ATOMIC_ORDERING]);
@@ -65,37 +68,65 @@ fn match_ordering_def_path(cx: &LateContext<'_, '_>, did: DefId, orderings: &[&s
6568
.any(|ordering| match_def_path(cx, did, &["core", "sync", "atomic", "Ordering", ordering]))
6669
}
6770

68-
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AtomicOrdering {
69-
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
70-
if_chain! {
71-
if let ExprKind::MethodCall(ref method_path, _, args) = &expr.kind;
72-
let method = method_path.ident.name.as_str();
73-
if type_is_atomic(cx, &args[0]);
74-
if method == "load" || method == "store";
75-
let ordering_arg = if method == "load" { &args[1] } else { &args[2] };
76-
if let ExprKind::Path(ref ordering_qpath) = ordering_arg.kind;
77-
if let Some(ordering_def_id) = cx.tables.qpath_res(ordering_qpath, ordering_arg.hir_id).opt_def_id();
78-
then {
79-
if method == "load" &&
80-
match_ordering_def_path(cx, ordering_def_id, &["Release", "AcqRel"]) {
81-
span_help_and_lint(
82-
cx,
83-
INVALID_ATOMIC_ORDERING,
84-
ordering_arg.span,
85-
"atomic loads cannot have `Release` and `AcqRel` ordering",
86-
"consider using ordering modes `Acquire`, `SeqCst` or `Relaxed`"
87-
);
88-
} else if method == "store" &&
89-
match_ordering_def_path(cx, ordering_def_id, &["Acquire", "AcqRel"]) {
90-
span_help_and_lint(
91-
cx,
92-
INVALID_ATOMIC_ORDERING,
93-
ordering_arg.span,
94-
"atomic stores cannot have `Acquire` and `AcqRel` ordering",
95-
"consider using ordering modes `Release`, `SeqCst` or `Relaxed`"
96-
);
97-
}
71+
fn check_atomic_load_store(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
72+
if_chain! {
73+
if let ExprKind::MethodCall(ref method_path, _, args) = &expr.kind;
74+
let method = method_path.ident.name.as_str();
75+
if type_is_atomic(cx, &args[0]);
76+
if method == "load" || method == "store";
77+
let ordering_arg = if method == "load" { &args[1] } else { &args[2] };
78+
if let ExprKind::Path(ref ordering_qpath) = ordering_arg.kind;
79+
if let Some(ordering_def_id) = cx.tables.qpath_res(ordering_qpath, ordering_arg.hir_id).opt_def_id();
80+
then {
81+
if method == "load" &&
82+
match_ordering_def_path(cx, ordering_def_id, &["Release", "AcqRel"]) {
83+
span_help_and_lint(
84+
cx,
85+
INVALID_ATOMIC_ORDERING,
86+
ordering_arg.span,
87+
"atomic loads cannot have `Release` and `AcqRel` ordering",
88+
"consider using ordering modes `Acquire`, `SeqCst` or `Relaxed`"
89+
);
90+
} else if method == "store" &&
91+
match_ordering_def_path(cx, ordering_def_id, &["Acquire", "AcqRel"]) {
92+
span_help_and_lint(
93+
cx,
94+
INVALID_ATOMIC_ORDERING,
95+
ordering_arg.span,
96+
"atomic stores cannot have `Acquire` and `AcqRel` ordering",
97+
"consider using ordering modes `Release`, `SeqCst` or `Relaxed`"
98+
);
9899
}
99100
}
100101
}
101102
}
103+
104+
fn check_memory_fence(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
105+
if_chain! {
106+
if let ExprKind::Call(ref func, ref args) = expr.kind;
107+
if let ExprKind::Path(ref func_qpath) = func.kind;
108+
if let Some(def_id) = cx.tables.qpath_res(func_qpath, func.hir_id).opt_def_id();
109+
if ["fence", "compiler_fence"]
110+
.iter()
111+
.any(|func| match_def_path(cx, def_id, &["core", "sync", "atomic", func]));
112+
if let ExprKind::Path(ref ordering_qpath) = &args[0].kind;
113+
if let Some(ordering_def_id) = cx.tables.qpath_res(ordering_qpath, args[0].hir_id).opt_def_id();
114+
if match_ordering_def_path(cx, ordering_def_id, &["Relaxed"]);
115+
then {
116+
span_help_and_lint(
117+
cx,
118+
INVALID_ATOMIC_ORDERING,
119+
args[0].span,
120+
"memory fences cannot have `Relaxed` ordering",
121+
"consider using ordering modes `Acquire`, `Release`, `AcqRel` or `SeqCst`"
122+
);
123+
}
124+
}
125+
}
126+
127+
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AtomicOrdering {
128+
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
129+
check_atomic_load_store(cx, expr);
130+
check_memory_fence(cx, expr);
131+
}
132+
}

clippy_lints/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
645645
&methods::SEARCH_IS_SOME,
646646
&methods::SHOULD_IMPLEMENT_TRAIT,
647647
&methods::SINGLE_CHAR_PATTERN,
648+
&methods::SKIP_WHILE_NEXT,
648649
&methods::STRING_EXTEND_CHARS,
649650
&methods::SUSPICIOUS_MAP,
650651
&methods::TEMPORARY_CSTRING_AS_PTR,
@@ -1223,6 +1224,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
12231224
LintId::of(&methods::SEARCH_IS_SOME),
12241225
LintId::of(&methods::SHOULD_IMPLEMENT_TRAIT),
12251226
LintId::of(&methods::SINGLE_CHAR_PATTERN),
1227+
LintId::of(&methods::SKIP_WHILE_NEXT),
12261228
LintId::of(&methods::STRING_EXTEND_CHARS),
12271229
LintId::of(&methods::SUSPICIOUS_MAP),
12281230
LintId::of(&methods::TEMPORARY_CSTRING_AS_PTR),
@@ -1475,6 +1477,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
14751477
LintId::of(&methods::FLAT_MAP_IDENTITY),
14761478
LintId::of(&methods::OPTION_AND_THEN_SOME),
14771479
LintId::of(&methods::SEARCH_IS_SOME),
1480+
LintId::of(&methods::SKIP_WHILE_NEXT),
14781481
LintId::of(&methods::SUSPICIOUS_MAP),
14791482
LintId::of(&methods::UNNECESSARY_FILTER_MAP),
14801483
LintId::of(&methods::USELESS_ASREF),

clippy_lints/src/methods/mod.rs

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,29 @@ declare_clippy_lint! {
375375
"using `filter(p).next()`, which is more succinctly expressed as `.find(p)`"
376376
}
377377

378+
declare_clippy_lint! {
379+
/// **What it does:** Checks for usage of `_.skip_while(condition).next()`.
380+
///
381+
/// **Why is this bad?** Readability, this can be written more concisely as
382+
/// `_.find(!condition)`.
383+
///
384+
/// **Known problems:** None.
385+
///
386+
/// **Example:**
387+
/// ```rust
388+
/// # let vec = vec![1];
389+
/// vec.iter().skip_while(|x| **x == 0).next();
390+
/// ```
391+
/// Could be written as
392+
/// ```rust
393+
/// # let vec = vec![1];
394+
/// vec.iter().find(|x| **x != 0);
395+
/// ```
396+
pub SKIP_WHILE_NEXT,
397+
complexity,
398+
"using `skip_while(p).next()`, which is more succinctly expressed as `.find(!p)`"
399+
}
400+
378401
declare_clippy_lint! {
379402
/// **What it does:** Checks for usage of `_.map(_).flatten(_)`,
380403
///
@@ -1041,7 +1064,8 @@ declare_clippy_lint! {
10411064
/// **What it does:** Checks for calls to `map` followed by a `count`.
10421065
///
10431066
/// **Why is this bad?** It looks suspicious. Maybe `map` was confused with `filter`.
1044-
/// If the `map` call is intentional, this should be rewritten.
1067+
/// If the `map` call is intentional, this should be rewritten. Or, if you intend to
1068+
/// drive the iterator to completion, you can just use `for_each` instead.
10451069
///
10461070
/// **Known problems:** None
10471071
///
@@ -1192,6 +1216,7 @@ declare_lint_pass!(Methods => [
11921216
SEARCH_IS_SOME,
11931217
TEMPORARY_CSTRING_AS_PTR,
11941218
FILTER_NEXT,
1219+
SKIP_WHILE_NEXT,
11951220
FILTER_MAP,
11961221
FILTER_MAP_NEXT,
11971222
FLAT_MAP_IDENTITY,
@@ -1237,6 +1262,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods {
12371262
["map_or", ..] => lint_map_or_none(cx, expr, arg_lists[0]),
12381263
["and_then", ..] => lint_option_and_then_some(cx, expr, arg_lists[0]),
12391264
["next", "filter"] => lint_filter_next(cx, expr, arg_lists[1]),
1265+
["next", "skip_while"] => lint_skip_while_next(cx, expr, arg_lists[1]),
12401266
["map", "filter"] => lint_filter_map(cx, expr, arg_lists[1], arg_lists[0]),
12411267
["map", "filter_map"] => lint_filter_map_map(cx, expr, arg_lists[1], arg_lists[0]),
12421268
["next", "filter_map"] => lint_filter_map_next(cx, expr, arg_lists[1]),
@@ -2530,6 +2556,24 @@ fn lint_filter_next<'a, 'tcx>(
25302556
}
25312557
}
25322558

2559+
/// lint use of `skip_while().next()` for `Iterators`
2560+
fn lint_skip_while_next<'a, 'tcx>(
2561+
cx: &LateContext<'a, 'tcx>,
2562+
expr: &'tcx hir::Expr<'_>,
2563+
_skip_while_args: &'tcx [hir::Expr<'_>],
2564+
) {
2565+
// lint if caller of `.skip_while().next()` is an Iterator
2566+
if match_trait_method(cx, expr, &paths::ITERATOR) {
2567+
span_help_and_lint(
2568+
cx,
2569+
SKIP_WHILE_NEXT,
2570+
expr.span,
2571+
"called `skip_while(p).next()` on an `Iterator`",
2572+
"this is more succinctly expressed by calling `.find(!p)` instead",
2573+
);
2574+
}
2575+
}
2576+
25332577
/// lint use of `filter().map()` for `Iterators`
25342578
fn lint_filter_map<'a, 'tcx>(
25352579
cx: &LateContext<'a, 'tcx>,
@@ -3014,7 +3058,7 @@ fn lint_suspicious_map(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>) {
30143058
SUSPICIOUS_MAP,
30153059
expr.span,
30163060
"this call to `map()` won't have an effect on the call to `count()`",
3017-
"make sure you did not confuse `map` with `filter`",
3061+
"make sure you did not confuse `map` with `filter` or `for_each`",
30183062
);
30193063
}
30203064

clippy_lints/src/mut_key.rs

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::utils::{match_def_path, paths, span_lint, trait_ref_of_method, walk_ptrs_ty};
2-
use rustc::ty::{Adt, Dynamic, Opaque, Param, RawPtr, Ref, Ty, TypeAndMut};
2+
use rustc::ty::{Adt, Array, RawPtr, Ref, Slice, Tuple, Ty, TypeAndMut};
33
use rustc_hir as hir;
44
use rustc_lint::{LateContext, LateLintPass};
55
use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -101,21 +101,24 @@ fn check_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, span: Span, ty: Ty<'tcx>) {
101101
if [&paths::HASHMAP, &paths::BTREEMAP, &paths::HASHSET, &paths::BTREESET]
102102
.iter()
103103
.any(|path| match_def_path(cx, def.did, &**path))
104+
&& is_mutable_type(cx, substs.type_at(0), span)
104105
{
105-
let key_type = concrete_type(substs.type_at(0));
106-
if let Some(key_type) = key_type {
107-
if !key_type.is_freeze(cx.tcx, cx.param_env, span) {
108-
span_lint(cx, MUTABLE_KEY_TYPE, span, "mutable key type");
109-
}
110-
}
106+
span_lint(cx, MUTABLE_KEY_TYPE, span, "mutable key type");
111107
}
112108
}
113109
}
114110

115-
fn concrete_type(ty: Ty<'_>) -> Option<Ty<'_>> {
111+
fn is_mutable_type<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>, span: Span) -> bool {
116112
match ty.kind {
117-
RawPtr(TypeAndMut { ty: inner_ty, .. }) | Ref(_, inner_ty, _) => concrete_type(inner_ty),
118-
Dynamic(..) | Opaque(..) | Param(..) => None,
119-
_ => Some(ty),
113+
RawPtr(TypeAndMut { ty: inner_ty, mutbl }) | Ref(_, inner_ty, mutbl) => {
114+
mutbl == hir::Mutability::Mut || is_mutable_type(cx, inner_ty, span)
115+
},
116+
Slice(inner_ty) => is_mutable_type(cx, inner_ty, span),
117+
Array(inner_ty, size) => {
118+
size.try_eval_usize(cx.tcx, cx.param_env).map_or(true, |u| u != 0) && is_mutable_type(cx, inner_ty, span)
119+
},
120+
Tuple(..) => ty.tuple_fields().any(|ty| is_mutable_type(cx, ty, span)),
121+
Adt(..) => cx.tcx.layout_of(cx.param_env.and(ty)).is_ok() && !ty.is_freeze(cx.tcx, cx.param_env, span),
122+
_ => false,
120123
}
121124
}

clippy_lints/src/needless_pass_by_value.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue {
114114
let preds = traits::elaborate_predicates(cx.tcx, cx.param_env.caller_bounds.to_vec())
115115
.filter(|p| !p.is_global())
116116
.filter_map(|pred| {
117-
if let ty::Predicate::Trait(poly_trait_ref) = pred {
117+
if let ty::Predicate::Trait(poly_trait_ref, _) = pred {
118118
if poly_trait_ref.def_id() == sized_trait || poly_trait_ref.skip_binder().has_escaping_bound_vars()
119119
{
120120
return None;

clippy_lints/src/utils/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1300,7 +1300,7 @@ pub fn is_must_use_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> boo
13001300
Tuple(ref substs) => substs.types().any(|ty| is_must_use_ty(cx, ty)),
13011301
Opaque(ref def_id, _) => {
13021302
for (predicate, _) in cx.tcx.predicates_of(*def_id).predicates {
1303-
if let ty::Predicate::Trait(ref poly_trait_predicate) = predicate {
1303+
if let ty::Predicate::Trait(ref poly_trait_predicate, _) = predicate {
13041304
if must_use_attr(&cx.tcx.get_attrs(poly_trait_predicate.skip_binder().trait_ref.def_id)).is_some() {
13051305
return true;
13061306
}

0 commit comments

Comments
 (0)