Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new lint [let_underscore_future] #9760

Merged
merged 8 commits into from
Nov 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3979,6 +3979,7 @@ Released 2018-09-13
[`len_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#len_zero
[`let_and_return`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_and_return
[`let_underscore_drop`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_drop
[`let_underscore_future`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_future
[`let_underscore_lock`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_lock
[`let_underscore_must_use`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_must_use
[`let_unit_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_unit_value
Expand Down
1 change: 1 addition & 0 deletions clippy_lints/foo.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hello
1 change: 1 addition & 0 deletions clippy_lints/src/declared_lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
crate::len_zero::LEN_WITHOUT_IS_EMPTY_INFO,
crate::len_zero::LEN_ZERO_INFO,
crate::let_if_seq::USELESS_LET_IF_SEQ_INFO,
crate::let_underscore::LET_UNDERSCORE_FUTURE_INFO,
crate::let_underscore::LET_UNDERSCORE_LOCK_INFO,
crate::let_underscore::LET_UNDERSCORE_MUST_USE_INFO,
crate::lifetimes::EXTRA_UNUSED_LIFETIMES_INFO,
Expand Down
55 changes: 48 additions & 7 deletions clippy_lints/src/let_underscore.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::ty::{is_must_use_ty, match_type};
use clippy_utils::ty::{implements_trait, is_must_use_ty, match_type};
use clippy_utils::{is_must_use_func_call, paths};
use rustc_hir::{Local, PatKind};
use rustc_lint::{LateContext, LateLintPass};
Expand Down Expand Up @@ -28,7 +28,7 @@ declare_clippy_lint! {
#[clippy::version = "1.42.0"]
pub LET_UNDERSCORE_MUST_USE,
restriction,
"non-binding let on a `#[must_use]` expression"
"non-binding `let` on a `#[must_use]` expression"
}

declare_clippy_lint! {
Expand Down Expand Up @@ -56,10 +56,41 @@ declare_clippy_lint! {
#[clippy::version = "1.43.0"]
pub LET_UNDERSCORE_LOCK,
correctness,
"non-binding let on a synchronization lock"
"non-binding `let` on a synchronization lock"
}

declare_lint_pass!(LetUnderscore => [LET_UNDERSCORE_MUST_USE, LET_UNDERSCORE_LOCK]);
declare_clippy_lint! {
/// ### What it does
/// Checks for `let _ = <expr>` where the resulting type of expr implements `Future`
///
/// ### Why is this bad?
/// Futures must be polled for work to be done. The original intention was most likely to await the future
/// and ignore the resulting value.
///
/// ### Example
/// ```rust
/// async fn foo() -> Result<(), ()> {
/// Ok(())
/// }
/// let _ = foo();
/// ```
///
/// Use instead:
/// ```rust
/// # async fn context() {
/// async fn foo() -> Result<(), ()> {
/// Ok(())
/// }
/// let _ = foo().await;
/// # }
/// ```
#[clippy::version = "1.66"]
pub LET_UNDERSCORE_FUTURE,
suspicious,
"non-binding `let` on a future"
}

declare_lint_pass!(LetUnderscore => [LET_UNDERSCORE_MUST_USE, LET_UNDERSCORE_LOCK, LET_UNDERSCORE_FUTURE]);

const SYNC_GUARD_PATHS: [&[&str]; 3] = [
&paths::PARKING_LOT_MUTEX_GUARD,
Expand All @@ -83,17 +114,27 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
cx,
LET_UNDERSCORE_LOCK,
local.span,
"non-binding let on a synchronization lock",
"non-binding `let` on a synchronization lock",
None,
"consider using an underscore-prefixed named \
binding or dropping explicitly with `std::mem::drop`",
);
} else if let Some(future_trait_def_id) = cx.tcx.lang_items().future_trait()
&& implements_trait(cx, cx.typeck_results().expr_ty(init), future_trait_def_id, &[]) {
span_lint_and_help(
cx,
LET_UNDERSCORE_FUTURE,
local.span,
"non-binding `let` on a future",
None,
"consider awaiting the future or dropping explicitly with `std::mem::drop`"
);
} else if is_must_use_ty(cx, cx.typeck_results().expr_ty(init)) {
span_lint_and_help(
cx,
LET_UNDERSCORE_MUST_USE,
local.span,
"non-binding let on an expression with `#[must_use]` type",
"non-binding `let` on an expression with `#[must_use]` type",
None,
"consider explicitly using expression value",
);
Expand All @@ -102,7 +143,7 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
cx,
LET_UNDERSCORE_MUST_USE,
local.span,
"non-binding let on a result of a `#[must_use]` function",
"non-binding `let` on a result of a `#[must_use]` function",
None,
"consider explicitly using function result",
);
Expand Down
20 changes: 20 additions & 0 deletions tests/ui/let_underscore_future.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use std::future::Future;

async fn some_async_fn() {}

fn sync_side_effects() {}
fn custom() -> impl Future<Output = ()> {
sync_side_effects();
async {}
}

fn do_something_to_future(future: &mut impl Future<Output = ()>) {}

fn main() {
let _ = some_async_fn();
let _ = custom();

let mut future = some_async_fn();
do_something_to_future(&mut future);
let _ = future;
}
27 changes: 27 additions & 0 deletions tests/ui/let_underscore_future.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
error: non-binding `let` on a future
--> $DIR/let_underscore_future.rs:14:5
|
LL | let _ = some_async_fn();
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider awaiting the future or dropping explicitly with `std::mem::drop`
= note: `-D clippy::let-underscore-future` implied by `-D warnings`

error: non-binding `let` on a future
--> $DIR/let_underscore_future.rs:15:5
|
LL | let _ = custom();
| ^^^^^^^^^^^^^^^^^
|
= help: consider awaiting the future or dropping explicitly with `std::mem::drop`

error: non-binding `let` on a future
--> $DIR/let_underscore_future.rs:19:5
|
LL | let _ = future;
| ^^^^^^^^^^^^^^^
|
= help: consider awaiting the future or dropping explicitly with `std::mem::drop`

error: aborting due to 3 previous errors

8 changes: 4 additions & 4 deletions tests/ui/let_underscore_lock.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error: non-binding let on a synchronization lock
error: non-binding `let` on a synchronization lock
--> $DIR/let_underscore_lock.rs:9:5
|
LL | let _ = p_m.lock();
Expand All @@ -7,23 +7,23 @@ LL | let _ = p_m.lock();
= help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop`
= note: `-D clippy::let-underscore-lock` implied by `-D warnings`

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

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

error: non-binding let on a synchronization lock
error: non-binding `let` on a synchronization lock
--> $DIR/let_underscore_lock.rs:16:5
|
LL | let _ = p_rw.write();
Expand Down
24 changes: 12 additions & 12 deletions tests/ui/let_underscore_must_use.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error: non-binding let on a result of a `#[must_use]` function
error: non-binding `let` on a result of a `#[must_use]` function
--> $DIR/let_underscore_must_use.rs:67:5
|
LL | let _ = f();
Expand All @@ -7,87 +7,87 @@ LL | let _ = f();
= help: consider explicitly using function result
= note: `-D clippy::let-underscore-must-use` implied by `-D warnings`

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

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

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

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

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

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

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

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

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

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

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