|
1 | 1 | 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}; |
3 | 3 | use clippy_utils::{is_must_use_func_call, paths};
|
4 | 4 | use rustc_hir::{Local, PatKind};
|
5 | 5 | use rustc_lint::{LateContext, LateLintPass};
|
@@ -59,7 +59,31 @@ declare_clippy_lint! {
|
59 | 59 | "non-binding let on a synchronization lock"
|
60 | 60 | }
|
61 | 61 |
|
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,ignore |
| 72 | + /// async fn foo() -> Result<(), ()> { } |
| 73 | + /// let _ = foo(); |
| 74 | + /// ``` |
| 75 | + /// |
| 76 | + /// Use instead: |
| 77 | + /// ```rust,ignore |
| 78 | + /// let _ = foo().await; |
| 79 | + /// ``` |
| 80 | + #[clippy::version = "1.66"] |
| 81 | + pub LET_UNDERSCORE_FUTURE, |
| 82 | + suspicious, |
| 83 | + "non-binding let on a future" |
| 84 | +} |
| 85 | + |
| 86 | +declare_lint_pass!(LetUnderscore => [LET_UNDERSCORE_MUST_USE, LET_UNDERSCORE_LOCK, LET_UNDERSCORE_FUTURE]); |
63 | 87 |
|
64 | 88 | const SYNC_GUARD_PATHS: [&[&str]; 3] = [
|
65 | 89 | &paths::PARKING_LOT_MUTEX_GUARD,
|
@@ -88,6 +112,16 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
|
88 | 112 | "consider using an underscore-prefixed named \
|
89 | 113 | binding or dropping explicitly with `std::mem::drop`",
|
90 | 114 | );
|
| 115 | + } else if let Some(future_trait_def_id) = cx.tcx.lang_items().future_trait() |
| 116 | + && implements_trait(cx, cx.typeck_results().expr_ty(init), future_trait_def_id, &[]) { |
| 117 | + span_lint_and_help( |
| 118 | + cx, |
| 119 | + LET_UNDERSCORE_FUTURE, |
| 120 | + local.span, |
| 121 | + "non-binding let on a future", |
| 122 | + None, |
| 123 | + "consider awaiting the future or dropping explicitly with `std::mem::drop`" |
| 124 | + ); |
91 | 125 | } else if is_must_use_ty(cx, cx.typeck_results().expr_ty(init)) {
|
92 | 126 | span_lint_and_help(
|
93 | 127 | cx,
|
|
0 commit comments