Skip to content

Commit d15e5e6

Browse files
committed
Auto merge of #9760 - SquareMan:let_underscore_future, r=llogiq
Add new lint [`let_underscore_future`] This closes #9721 --- changelog: add new lint [`let_underscore_future`]
2 parents e547411 + 7c5b188 commit d15e5e6

8 files changed

+114
-23
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4123,6 +4123,7 @@ Released 2018-09-13
41234123
[`len_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#len_zero
41244124
[`let_and_return`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_and_return
41254125
[`let_underscore_drop`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_drop
4126+
[`let_underscore_future`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_future
41264127
[`let_underscore_lock`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_lock
41274128
[`let_underscore_must_use`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_must_use
41284129
[`let_unit_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_unit_value

clippy_lints/foo.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Hello

clippy_lints/src/declared_lints.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
215215
crate::len_zero::LEN_WITHOUT_IS_EMPTY_INFO,
216216
crate::len_zero::LEN_ZERO_INFO,
217217
crate::let_if_seq::USELESS_LET_IF_SEQ_INFO,
218+
crate::let_underscore::LET_UNDERSCORE_FUTURE_INFO,
218219
crate::let_underscore::LET_UNDERSCORE_LOCK_INFO,
219220
crate::let_underscore::LET_UNDERSCORE_MUST_USE_INFO,
220221
crate::lifetimes::EXTRA_UNUSED_LIFETIMES_INFO,

clippy_lints/src/let_underscore.rs

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use clippy_utils::diagnostics::span_lint_and_help;
2-
use clippy_utils::ty::{is_must_use_ty, match_type};
2+
use clippy_utils::ty::{implements_trait, is_must_use_ty, match_type};
33
use clippy_utils::{is_must_use_func_call, paths};
44
use rustc_hir::{Local, PatKind};
55
use rustc_lint::{LateContext, LateLintPass};
@@ -28,7 +28,7 @@ declare_clippy_lint! {
2828
#[clippy::version = "1.42.0"]
2929
pub LET_UNDERSCORE_MUST_USE,
3030
restriction,
31-
"non-binding let on a `#[must_use]` expression"
31+
"non-binding `let` on a `#[must_use]` expression"
3232
}
3333

3434
declare_clippy_lint! {
@@ -56,10 +56,41 @@ declare_clippy_lint! {
5656
#[clippy::version = "1.43.0"]
5757
pub LET_UNDERSCORE_LOCK,
5858
correctness,
59-
"non-binding let on a synchronization lock"
59+
"non-binding `let` on a synchronization lock"
6060
}
6161

62-
declare_lint_pass!(LetUnderscore => [LET_UNDERSCORE_MUST_USE, LET_UNDERSCORE_LOCK]);
62+
declare_clippy_lint! {
63+
/// ### What it does
64+
/// Checks for `let _ = <expr>` where the resulting type of expr implements `Future`
65+
///
66+
/// ### Why is this bad?
67+
/// Futures must be polled for work to be done. The original intention was most likely to await the future
68+
/// and ignore the resulting value.
69+
///
70+
/// ### Example
71+
/// ```rust
72+
/// async fn foo() -> Result<(), ()> {
73+
/// Ok(())
74+
/// }
75+
/// let _ = foo();
76+
/// ```
77+
///
78+
/// Use instead:
79+
/// ```rust
80+
/// # async fn context() {
81+
/// async fn foo() -> Result<(), ()> {
82+
/// Ok(())
83+
/// }
84+
/// let _ = foo().await;
85+
/// # }
86+
/// ```
87+
#[clippy::version = "1.66"]
88+
pub LET_UNDERSCORE_FUTURE,
89+
suspicious,
90+
"non-binding `let` on a future"
91+
}
92+
93+
declare_lint_pass!(LetUnderscore => [LET_UNDERSCORE_MUST_USE, LET_UNDERSCORE_LOCK, LET_UNDERSCORE_FUTURE]);
6394

6495
const SYNC_GUARD_PATHS: [&[&str]; 3] = [
6596
&paths::PARKING_LOT_MUTEX_GUARD,
@@ -83,17 +114,27 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
83114
cx,
84115
LET_UNDERSCORE_LOCK,
85116
local.span,
86-
"non-binding let on a synchronization lock",
117+
"non-binding `let` on a synchronization lock",
87118
None,
88119
"consider using an underscore-prefixed named \
89120
binding or dropping explicitly with `std::mem::drop`",
90121
);
122+
} else if let Some(future_trait_def_id) = cx.tcx.lang_items().future_trait()
123+
&& implements_trait(cx, cx.typeck_results().expr_ty(init), future_trait_def_id, &[]) {
124+
span_lint_and_help(
125+
cx,
126+
LET_UNDERSCORE_FUTURE,
127+
local.span,
128+
"non-binding `let` on a future",
129+
None,
130+
"consider awaiting the future or dropping explicitly with `std::mem::drop`"
131+
);
91132
} else if is_must_use_ty(cx, cx.typeck_results().expr_ty(init)) {
92133
span_lint_and_help(
93134
cx,
94135
LET_UNDERSCORE_MUST_USE,
95136
local.span,
96-
"non-binding let on an expression with `#[must_use]` type",
137+
"non-binding `let` on an expression with `#[must_use]` type",
97138
None,
98139
"consider explicitly using expression value",
99140
);
@@ -102,7 +143,7 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
102143
cx,
103144
LET_UNDERSCORE_MUST_USE,
104145
local.span,
105-
"non-binding let on a result of a `#[must_use]` function",
146+
"non-binding `let` on a result of a `#[must_use]` function",
106147
None,
107148
"consider explicitly using function result",
108149
);

tests/ui/let_underscore_future.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
use std::future::Future;
2+
3+
async fn some_async_fn() {}
4+
5+
fn sync_side_effects() {}
6+
fn custom() -> impl Future<Output = ()> {
7+
sync_side_effects();
8+
async {}
9+
}
10+
11+
fn do_something_to_future(future: &mut impl Future<Output = ()>) {}
12+
13+
fn main() {
14+
let _ = some_async_fn();
15+
let _ = custom();
16+
17+
let mut future = some_async_fn();
18+
do_something_to_future(&mut future);
19+
let _ = future;
20+
}

tests/ui/let_underscore_future.stderr

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
error: non-binding `let` on a future
2+
--> $DIR/let_underscore_future.rs:14:5
3+
|
4+
LL | let _ = some_async_fn();
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= help: consider awaiting the future or dropping explicitly with `std::mem::drop`
8+
= note: `-D clippy::let-underscore-future` implied by `-D warnings`
9+
10+
error: non-binding `let` on a future
11+
--> $DIR/let_underscore_future.rs:15:5
12+
|
13+
LL | let _ = custom();
14+
| ^^^^^^^^^^^^^^^^^
15+
|
16+
= help: consider awaiting the future or dropping explicitly with `std::mem::drop`
17+
18+
error: non-binding `let` on a future
19+
--> $DIR/let_underscore_future.rs:19:5
20+
|
21+
LL | let _ = future;
22+
| ^^^^^^^^^^^^^^^
23+
|
24+
= help: consider awaiting the future or dropping explicitly with `std::mem::drop`
25+
26+
error: aborting due to 3 previous errors
27+

tests/ui/let_underscore_lock.stderr

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: non-binding let on a synchronization lock
1+
error: non-binding `let` on a synchronization lock
22
--> $DIR/let_underscore_lock.rs:9:5
33
|
44
LL | let _ = p_m.lock();
@@ -7,23 +7,23 @@ LL | let _ = p_m.lock();
77
= help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop`
88
= note: `-D clippy::let-underscore-lock` implied by `-D warnings`
99

10-
error: non-binding let on a synchronization lock
10+
error: non-binding `let` on a synchronization lock
1111
--> $DIR/let_underscore_lock.rs:12:5
1212
|
1313
LL | let _ = p_m1.lock();
1414
| ^^^^^^^^^^^^^^^^^^^^
1515
|
1616
= help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop`
1717

18-
error: non-binding let on a synchronization lock
18+
error: non-binding `let` on a synchronization lock
1919
--> $DIR/let_underscore_lock.rs:15:5
2020
|
2121
LL | let _ = p_rw.read();
2222
| ^^^^^^^^^^^^^^^^^^^^
2323
|
2424
= help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop`
2525

26-
error: non-binding let on a synchronization lock
26+
error: non-binding `let` on a synchronization lock
2727
--> $DIR/let_underscore_lock.rs:16:5
2828
|
2929
LL | let _ = p_rw.write();

tests/ui/let_underscore_must_use.stderr

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: non-binding let on a result of a `#[must_use]` function
1+
error: non-binding `let` on a result of a `#[must_use]` function
22
--> $DIR/let_underscore_must_use.rs:67:5
33
|
44
LL | let _ = f();
@@ -7,87 +7,87 @@ LL | let _ = f();
77
= help: consider explicitly using function result
88
= note: `-D clippy::let-underscore-must-use` implied by `-D warnings`
99

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

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

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

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

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

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

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

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

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

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

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

0 commit comments

Comments
 (0)