Skip to content

Commit be11c3d

Browse files
committed
add lint
1 parent 5b42a76 commit be11c3d

File tree

8 files changed

+110
-21
lines changed

8 files changed

+110
-21
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -1153,6 +1153,7 @@ Released 2018-09-13
11531153
[`len_without_is_empty`]: https://rust-lang.github.io/rust-clippy/master/index.html#len_without_is_empty
11541154
[`len_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#len_zero
11551155
[`let_and_return`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_and_return
1156+
[`let_underscore_lock`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_lock
11561157
[`let_underscore_must_use`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_must_use
11571158
[`let_unit_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_unit_value
11581159
[`linkedlist`]: https://rust-lang.github.io/rust-clippy/master/index.html#linkedlist

README.md

+1-1
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 349 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
9+
[There are 350 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/let_underscore.rs

+61-18
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use rustc_hir::*;
44
use rustc_lint::{LateContext, LateLintPass};
55
use rustc_session::{declare_lint_pass, declare_tool_lint};
66

7-
use crate::utils::{is_must_use_func_call, is_must_use_ty, span_lint_and_help};
7+
use crate::utils::{is_must_use_func_call, is_must_use_ty, match_def_path, paths, span_lint_and_help};
88

99
declare_clippy_lint! {
1010
/// **What it does:** Checks for `let _ = <expr>`
@@ -30,7 +30,35 @@ declare_clippy_lint! {
3030
"non-binding let on a `#[must_use]` expression"
3131
}
3232

33-
declare_lint_pass!(LetUnderscore => [LET_UNDERSCORE_MUST_USE]);
33+
declare_clippy_lint! {
34+
/// **What it does:** Checks for `let _ = sync_primitive.lock()`
35+
///
36+
/// **Why is this bad?** This statement locks the synchronization
37+
/// primitive and immediately drops the lock, which is probably
38+
/// not intended. To extend lock lifetime to the end of the scope,
39+
/// use an underscore-prefixed name instead (i.e. _lock).
40+
///
41+
/// **Known problems:** None.
42+
///
43+
/// **Example:**
44+
///
45+
/// Bad:
46+
/// ```rust
47+
/// let _ = mutex.lock();
48+
/// ```
49+
///
50+
/// Good:
51+
/// ```rust
52+
/// let _lock = mutex.lock();
53+
/// ```
54+
pub LET_UNDERSCORE_LOCK,
55+
correctness,
56+
"non-binding let on a synchronization lock"
57+
}
58+
59+
declare_lint_pass!(LetUnderscore => [LET_UNDERSCORE_MUST_USE, LET_UNDERSCORE_LOCK]);
60+
61+
const LOCK_METHODS_PATHS: [&[&str]; 3] = [&paths::MUTEX_LOCK, &paths::RWLOCK_READ, &paths::RWLOCK_WRITE];
3462

3563
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetUnderscore {
3664
fn check_stmt(&mut self, cx: &LateContext<'_, '_>, stmt: &Stmt<'_>) {
@@ -43,22 +71,37 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetUnderscore {
4371
if let PatKind::Wild = local.pat.kind;
4472
if let Some(ref init) = local.init;
4573
then {
46-
if is_must_use_ty(cx, cx.tables.expr_ty(init)) {
47-
span_lint_and_help(
48-
cx,
49-
LET_UNDERSCORE_MUST_USE,
50-
stmt.span,
51-
"non-binding let on an expression with `#[must_use]` type",
52-
"consider explicitly using expression value"
53-
)
54-
} else if is_must_use_func_call(cx, init) {
55-
span_lint_and_help(
56-
cx,
57-
LET_UNDERSCORE_MUST_USE,
58-
stmt.span,
59-
"non-binding let on a result of a `#[must_use]` function",
60-
"consider explicitly using function result"
61-
)
74+
if_chain! {
75+
if let ExprKind::MethodCall(_, _, _) = init.kind;
76+
let method_did = cx.tables.type_dependent_def_id(init.hir_id).unwrap();
77+
if LOCK_METHODS_PATHS.iter().any(|path| match_def_path(cx, method_did, path));
78+
then {
79+
span_lint_and_help(
80+
cx,
81+
LET_UNDERSCORE_LOCK,
82+
stmt.span,
83+
"non-binding let on an a synchronization lock",
84+
"consider using an underscore-prefixed named binding"
85+
)
86+
} else {
87+
if is_must_use_ty(cx, cx.tables.expr_ty(init)) {
88+
span_lint_and_help(
89+
cx,
90+
LET_UNDERSCORE_MUST_USE,
91+
stmt.span,
92+
"non-binding let on an expression with `#[must_use]` type",
93+
"consider explicitly using expression value"
94+
)
95+
} else if is_must_use_func_call(cx, init) {
96+
span_lint_and_help(
97+
cx,
98+
LET_UNDERSCORE_MUST_USE,
99+
stmt.span,
100+
"non-binding let on a result of a `#[must_use]` function",
101+
"consider explicitly using function result"
102+
)
103+
}
104+
}
62105
}
63106
}
64107
}

clippy_lints/src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
565565
&len_zero::LEN_WITHOUT_IS_EMPTY,
566566
&len_zero::LEN_ZERO,
567567
&let_if_seq::USELESS_LET_IF_SEQ,
568+
&let_underscore::LET_UNDERSCORE_LOCK,
568569
&let_underscore::LET_UNDERSCORE_MUST_USE,
569570
&lifetimes::EXTRA_UNUSED_LIFETIMES,
570571
&lifetimes::NEEDLESS_LIFETIMES,
@@ -1168,6 +1169,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
11681169
LintId::of(&len_zero::LEN_WITHOUT_IS_EMPTY),
11691170
LintId::of(&len_zero::LEN_ZERO),
11701171
LintId::of(&let_if_seq::USELESS_LET_IF_SEQ),
1172+
LintId::of(&let_underscore::LET_UNDERSCORE_LOCK),
11711173
LintId::of(&lifetimes::EXTRA_UNUSED_LIFETIMES),
11721174
LintId::of(&lifetimes::NEEDLESS_LIFETIMES),
11731175
LintId::of(&literal_representation::INCONSISTENT_DIGIT_GROUPING),
@@ -1551,6 +1553,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
15511553
LintId::of(&infinite_iter::INFINITE_ITER),
15521554
LintId::of(&inherent_to_string::INHERENT_TO_STRING_SHADOW_DISPLAY),
15531555
LintId::of(&inline_fn_without_body::INLINE_FN_WITHOUT_BODY),
1556+
LintId::of(&let_underscore::LET_UNDERSCORE_LOCK),
15541557
LintId::of(&literal_representation::MISTYPED_LITERAL_SUFFIXES),
15551558
LintId::of(&loops::FOR_LOOP_OVER_OPTION),
15561559
LintId::of(&loops::FOR_LOOP_OVER_RESULT),

clippy_lints/src/utils/paths.rs

+3
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ pub const MEM_REPLACE: [&str; 3] = ["core", "mem", "replace"];
5858
pub const MEM_UNINITIALIZED: [&str; 3] = ["core", "mem", "uninitialized"];
5959
pub const MEM_ZEROED: [&str; 3] = ["core", "mem", "zeroed"];
6060
pub const MUTEX: [&str; 4] = ["std", "sync", "mutex", "Mutex"];
61+
pub const MUTEX_LOCK: [&str; 5] = ["std", "sync", "mutex", "Mutex", "lock"];
6162
pub const OPEN_OPTIONS: [&str; 3] = ["std", "fs", "OpenOptions"];
6263
pub const OPS_MODULE: [&str; 2] = ["core", "ops"];
6364
pub const OPTION: [&str; 3] = ["core", "option", "Option"];
@@ -100,6 +101,8 @@ pub const REPEAT: [&str; 3] = ["core", "iter", "repeat"];
100101
pub const RESULT: [&str; 3] = ["core", "result", "Result"];
101102
pub const RESULT_ERR: [&str; 4] = ["core", "result", "Result", "Err"];
102103
pub const RESULT_OK: [&str; 4] = ["core", "result", "Result", "Ok"];
104+
pub const RWLOCK_READ: [&str; 5] = ["std", "sync", "rwlock", "RwLock", "read"];
105+
pub const RWLOCK_WRITE: [&str; 5] = ["std", "sync", "rwlock", "RwLock", "write"];
103106
pub const SERDE_DE_VISITOR: [&str; 3] = ["serde", "de", "Visitor"];
104107
pub const SLICE_INTO_VEC: [&str; 4] = ["alloc", "slice", "<impl [T]>", "into_vec"];
105108
pub const SLICE_ITER: [&str; 3] = ["core", "slice", "Iter"];

src/lintlist/mod.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ pub use lint::Lint;
66
pub use lint::LINT_LEVELS;
77

88
// begin lint list, do not remove this comment, it’s used in `update_lints`
9-
pub const ALL_LINTS: [Lint; 349] = [
9+
pub const ALL_LINTS: [Lint; 350] = [
1010
Lint {
1111
name: "absurd_extreme_comparisons",
1212
group: "correctness",
@@ -959,6 +959,13 @@ pub const ALL_LINTS: [Lint; 349] = [
959959
deprecation: None,
960960
module: "returns",
961961
},
962+
Lint {
963+
name: "let_underscore_lock",
964+
group: "correctness",
965+
desc: "non-binding let on a synchronization lock",
966+
deprecation: None,
967+
module: "let_underscore",
968+
},
962969
Lint {
963970
name: "let_underscore_must_use",
964971
group: "restriction",

tests/ui/let_underscore.rs

+7
Original file line numberDiff line numberDiff line change
@@ -88,4 +88,11 @@ fn main() {
8888
let _ = a.map(|_| ());
8989

9090
let _ = a;
91+
92+
let m = std::sync::Mutex::new(());
93+
let rw = std::sync::RwLock::new(());
94+
95+
let _ = m.lock();
96+
let _ = rw.read();
97+
let _ = rw.write();
9198
}

tests/ui/let_underscore.stderr

+26-1
Original file line numberDiff line numberDiff line change
@@ -95,5 +95,30 @@ LL | let _ = a;
9595
|
9696
= help: consider explicitly using expression value
9797

98-
error: aborting due to 12 previous errors
98+
error: non-binding let on an a synchronization lock
99+
--> $DIR/let_underscore.rs:95:5
100+
|
101+
LL | let _ = m.lock();
102+
| ^^^^^^^^^^^^^^^^^
103+
|
104+
= note: `#[deny(clippy::let_underscore_lock)]` on by default
105+
= help: consider using an underscore-prefixed named binding
106+
107+
error: non-binding let on an a synchronization lock
108+
--> $DIR/let_underscore.rs:96:5
109+
|
110+
LL | let _ = rw.read();
111+
| ^^^^^^^^^^^^^^^^^^
112+
|
113+
= help: consider using an underscore-prefixed named binding
114+
115+
error: non-binding let on an a synchronization lock
116+
--> $DIR/let_underscore.rs:97:5
117+
|
118+
LL | let _ = rw.write();
119+
| ^^^^^^^^^^^^^^^^^^^
120+
|
121+
= help: consider using an underscore-prefixed named binding
122+
123+
error: aborting due to 15 previous errors
99124

0 commit comments

Comments
 (0)