Skip to content

Commit 668bc48

Browse files
committed
Auto merge of rust-lang#5101 - Areredify:let_underscore_lock, r=flip1995
add `let_underscore_lock` lint closes rust-lang#1574 changelog: add `let_underscore_lock` lint I am not entirely sure about my docs/messages wording here, improvements are welcome
2 parents 8002bad + 63ab7a5 commit 668bc48

10 files changed

+139
-18
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
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

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

Lines changed: 47 additions & 4 deletions
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_type, paths, span_lint_and_help};
88

99
declare_clippy_lint! {
1010
/// **What it does:** Checks for `let _ = <expr>`
@@ -30,7 +30,40 @@ 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_lock`
35+
///
36+
/// **Why is this bad?** This statement immediately drops the lock instead of
37+
/// extending it's lifetime to the end of the scope, which is often not intended.
38+
/// To extend lock lifetime to the end of the scope, use an underscore-prefixed
39+
/// name instead (i.e. _lock). If you want to explicitly drop the lock,
40+
/// `std::mem::drop` conveys your intention better and is less error-prone.
41+
///
42+
/// **Known problems:** None.
43+
///
44+
/// **Example:**
45+
///
46+
/// Bad:
47+
/// ```rust,ignore
48+
/// let _ = mutex.lock();
49+
/// ```
50+
///
51+
/// Good:
52+
/// ```rust,ignore
53+
/// let _lock = mutex.lock();
54+
/// ```
55+
pub LET_UNDERSCORE_LOCK,
56+
correctness,
57+
"non-binding let on a synchronization lock"
58+
}
59+
60+
declare_lint_pass!(LetUnderscore => [LET_UNDERSCORE_MUST_USE, LET_UNDERSCORE_LOCK]);
61+
62+
const SYNC_GUARD_PATHS: [&[&str]; 3] = [
63+
&paths::MUTEX_GUARD,
64+
&paths::RWLOCK_READ_GUARD,
65+
&paths::RWLOCK_WRITE_GUARD,
66+
];
3467

3568
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetUnderscore {
3669
fn check_stmt(&mut self, cx: &LateContext<'_, '_>, stmt: &Stmt<'_>) {
@@ -43,8 +76,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetUnderscore {
4376
if let PatKind::Wild = local.pat.kind;
4477
if let Some(ref init) = local.init;
4578
then {
46-
if is_must_use_ty(cx, cx.tables.expr_ty(init)) {
47-
span_lint_and_help(
79+
let check_ty = |ty| SYNC_GUARD_PATHS.iter().any(|path| match_type(cx, ty, path));
80+
if cx.tables.expr_ty(init).walk().any(check_ty) {
81+
span_lint_and_help(
82+
cx,
83+
LET_UNDERSCORE_LOCK,
84+
stmt.span,
85+
"non-binding let on a synchronization lock",
86+
"consider using an underscore-prefixed named \
87+
binding or dropping explicitly with `std::mem::drop`"
88+
)
89+
} else if is_must_use_ty(cx, cx.tables.expr_ty(init)) {
90+
span_lint_and_help(
4891
cx,
4992
LET_UNDERSCORE_MUST_USE,
5093
stmt.span,

clippy_lints/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
566566
&len_zero::LEN_WITHOUT_IS_EMPTY,
567567
&len_zero::LEN_ZERO,
568568
&let_if_seq::USELESS_LET_IF_SEQ,
569+
&let_underscore::LET_UNDERSCORE_LOCK,
569570
&let_underscore::LET_UNDERSCORE_MUST_USE,
570571
&lifetimes::EXTRA_UNUSED_LIFETIMES,
571572
&lifetimes::NEEDLESS_LIFETIMES,
@@ -1171,6 +1172,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
11711172
LintId::of(&len_zero::LEN_WITHOUT_IS_EMPTY),
11721173
LintId::of(&len_zero::LEN_ZERO),
11731174
LintId::of(&let_if_seq::USELESS_LET_IF_SEQ),
1175+
LintId::of(&let_underscore::LET_UNDERSCORE_LOCK),
11741176
LintId::of(&lifetimes::EXTRA_UNUSED_LIFETIMES),
11751177
LintId::of(&lifetimes::NEEDLESS_LIFETIMES),
11761178
LintId::of(&literal_representation::INCONSISTENT_DIGIT_GROUPING),
@@ -1556,6 +1558,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
15561558
LintId::of(&infinite_iter::INFINITE_ITER),
15571559
LintId::of(&inherent_to_string::INHERENT_TO_STRING_SHADOW_DISPLAY),
15581560
LintId::of(&inline_fn_without_body::INLINE_FN_WITHOUT_BODY),
1561+
LintId::of(&let_underscore::LET_UNDERSCORE_LOCK),
15591562
LintId::of(&literal_representation::MISTYPED_LITERAL_SUFFIXES),
15601563
LintId::of(&loops::FOR_LOOP_OVER_OPTION),
15611564
LintId::of(&loops::FOR_LOOP_OVER_RESULT),

clippy_lints/src/utils/paths.rs

Lines changed: 3 additions & 0 deletions
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_GUARD: [&str; 4] = ["std", "sync", "mutex", "MutexGuard"];
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_GUARD: [&str; 4] = ["std", "sync", "rwlock", "RwLockReadGuard"];
105+
pub const RWLOCK_WRITE_GUARD: [&str; 4] = ["std", "sync", "rwlock", "RwLockWriteGuard"];
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

Lines changed: 8 additions & 1 deletion
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; 350] = [
9+
pub const ALL_LINTS: [Lint; 351] = [
1010
Lint {
1111
name: "absurd_extreme_comparisons",
1212
group: "correctness",
@@ -959,6 +959,13 @@ pub const ALL_LINTS: [Lint; 350] = [
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_lock.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#![warn(clippy::let_underscore_lock)]
2+
3+
fn main() {
4+
let m = std::sync::Mutex::new(());
5+
let rw = std::sync::RwLock::new(());
6+
7+
let _ = m.lock();
8+
let _ = rw.read();
9+
let _ = rw.write();
10+
let _ = m.try_lock();
11+
let _ = rw.try_read();
12+
let _ = rw.try_write();
13+
}

tests/ui/let_underscore_lock.stderr

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
error: non-binding let on a synchronization lock
2+
--> $DIR/let_underscore_lock.rs:7:5
3+
|
4+
LL | let _ = m.lock();
5+
| ^^^^^^^^^^^^^^^^^
6+
|
7+
= note: `-D clippy::let-underscore-lock` implied by `-D warnings`
8+
= help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop`
9+
10+
error: non-binding let on a synchronization lock
11+
--> $DIR/let_underscore_lock.rs:8:5
12+
|
13+
LL | let _ = rw.read();
14+
| ^^^^^^^^^^^^^^^^^^
15+
|
16+
= help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop`
17+
18+
error: non-binding let on a synchronization lock
19+
--> $DIR/let_underscore_lock.rs:9:5
20+
|
21+
LL | let _ = rw.write();
22+
| ^^^^^^^^^^^^^^^^^^^
23+
|
24+
= help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop`
25+
26+
error: non-binding let on a synchronization lock
27+
--> $DIR/let_underscore_lock.rs:10:5
28+
|
29+
LL | let _ = m.try_lock();
30+
| ^^^^^^^^^^^^^^^^^^^^^
31+
|
32+
= help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop`
33+
34+
error: non-binding let on a synchronization lock
35+
--> $DIR/let_underscore_lock.rs:11:5
36+
|
37+
LL | let _ = rw.try_read();
38+
| ^^^^^^^^^^^^^^^^^^^^^^
39+
|
40+
= help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop`
41+
42+
error: non-binding let on a synchronization lock
43+
--> $DIR/let_underscore_lock.rs:12:5
44+
|
45+
LL | let _ = rw.try_write();
46+
| ^^^^^^^^^^^^^^^^^^^^^^^
47+
|
48+
= help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop`
49+
50+
error: aborting due to 6 previous errors
51+
File renamed without changes.

tests/ui/let_underscore.stderr renamed to tests/ui/let_underscore_must_use.stderr

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: non-binding let on a result of a `#[must_use]` function
2-
--> $DIR/let_underscore.rs:66:5
2+
--> $DIR/let_underscore_must_use.rs:66:5
33
|
44
LL | let _ = f();
55
| ^^^^^^^^^^^^
@@ -8,87 +8,87 @@ LL | let _ = f();
88
= help: consider explicitly using function result
99

1010
error: non-binding let on an expression with `#[must_use]` type
11-
--> $DIR/let_underscore.rs:67:5
11+
--> $DIR/let_underscore_must_use.rs:67:5
1212
|
1313
LL | let _ = g();
1414
| ^^^^^^^^^^^^
1515
|
1616
= help: consider explicitly using expression value
1717

1818
error: non-binding let on a result of a `#[must_use]` function
19-
--> $DIR/let_underscore.rs:69:5
19+
--> $DIR/let_underscore_must_use.rs:69:5
2020
|
2121
LL | let _ = l(0_u32);
2222
| ^^^^^^^^^^^^^^^^^
2323
|
2424
= help: consider explicitly using function result
2525

2626
error: non-binding let on a result of a `#[must_use]` function
27-
--> $DIR/let_underscore.rs:73:5
27+
--> $DIR/let_underscore_must_use.rs:73:5
2828
|
2929
LL | let _ = s.f();
3030
| ^^^^^^^^^^^^^^
3131
|
3232
= help: consider explicitly using function result
3333

3434
error: non-binding let on an expression with `#[must_use]` type
35-
--> $DIR/let_underscore.rs:74:5
35+
--> $DIR/let_underscore_must_use.rs:74:5
3636
|
3737
LL | let _ = s.g();
3838
| ^^^^^^^^^^^^^^
3939
|
4040
= help: consider explicitly using expression value
4141

4242
error: non-binding let on a result of a `#[must_use]` function
43-
--> $DIR/let_underscore.rs:77:5
43+
--> $DIR/let_underscore_must_use.rs:77:5
4444
|
4545
LL | let _ = S::h();
4646
| ^^^^^^^^^^^^^^^
4747
|
4848
= help: consider explicitly using function result
4949

5050
error: non-binding let on an expression with `#[must_use]` type
51-
--> $DIR/let_underscore.rs:78:5
51+
--> $DIR/let_underscore_must_use.rs:78:5
5252
|
5353
LL | let _ = S::p();
5454
| ^^^^^^^^^^^^^^^
5555
|
5656
= help: consider explicitly using expression value
5757

5858
error: non-binding let on a result of a `#[must_use]` function
59-
--> $DIR/let_underscore.rs:80:5
59+
--> $DIR/let_underscore_must_use.rs:80:5
6060
|
6161
LL | let _ = S::a();
6262
| ^^^^^^^^^^^^^^^
6363
|
6464
= help: consider explicitly using function result
6565

6666
error: non-binding let on an expression with `#[must_use]` type
67-
--> $DIR/let_underscore.rs:82:5
67+
--> $DIR/let_underscore_must_use.rs:82:5
6868
|
6969
LL | let _ = if true { Ok(()) } else { Err(()) };
7070
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
7171
|
7272
= help: consider explicitly using expression value
7373

7474
error: non-binding let on a result of a `#[must_use]` function
75-
--> $DIR/let_underscore.rs:86:5
75+
--> $DIR/let_underscore_must_use.rs:86:5
7676
|
7777
LL | let _ = a.is_ok();
7878
| ^^^^^^^^^^^^^^^^^^
7979
|
8080
= help: consider explicitly using function result
8181

8282
error: non-binding let on an expression with `#[must_use]` type
83-
--> $DIR/let_underscore.rs:88:5
83+
--> $DIR/let_underscore_must_use.rs:88:5
8484
|
8585
LL | let _ = a.map(|_| ());
8686
| ^^^^^^^^^^^^^^^^^^^^^^
8787
|
8888
= help: consider explicitly using expression value
8989

9090
error: non-binding let on an expression with `#[must_use]` type
91-
--> $DIR/let_underscore.rs:90:5
91+
--> $DIR/let_underscore_must_use.rs:90:5
9292
|
9393
LL | let _ = a;
9494
| ^^^^^^^^^^

0 commit comments

Comments
 (0)