11use clippy_utils:: diagnostics:: span_lint_and_help;
2- use clippy_utils:: ty:: { is_must_use_ty, is_type_diagnostic_item , match_type} ;
2+ use clippy_utils:: ty:: { is_must_use_ty, match_type} ;
33use clippy_utils:: { is_must_use_func_call, paths} ;
4- use if_chain:: if_chain;
54use rustc_hir:: { Local , PatKind } ;
65use rustc_lint:: { LateContext , LateLintPass } ;
76use rustc_middle:: lint:: in_external_macro;
87use rustc_middle:: ty:: subst:: GenericArgKind ;
98use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
10- use rustc_span:: { sym, Symbol } ;
119
1210declare_clippy_lint ! {
1311 /// ### What it does
@@ -35,8 +33,9 @@ declare_clippy_lint! {
3533
3634declare_clippy_lint ! {
3735 /// ### What it does
38- /// Checks for `let _ = sync_lock`.
39- /// This supports `mutex` and `rwlock` in `std::sync` and `parking_lot`.
36+ /// Checks for `let _ = sync_lock`. This supports `mutex` and `rwlock` in
37+ /// `parking_lot`. For `std` locks see the `rustc` lint
38+ /// [`let_underscore_lock`](https://doc.rust-lang.org/nightly/rustc/lints/listing/deny-by-default.html#let-underscore-lock)
4039 ///
4140 /// ### Why is this bad?
4241 /// This statement immediately drops the lock instead of
@@ -60,47 +59,7 @@ declare_clippy_lint! {
6059 "non-binding let on a synchronization lock"
6160}
6261
63- declare_clippy_lint ! {
64- /// ### What it does
65- /// Checks for `let _ = <expr>`
66- /// where expr has a type that implements `Drop`
67- ///
68- /// ### Why is this bad?
69- /// This statement immediately drops the initializer
70- /// expression instead of extending its lifetime to the end of the scope, which
71- /// is often not intended. To extend the expression's lifetime to the end of the
72- /// scope, use an underscore-prefixed name instead (i.e. _var). If you want to
73- /// explicitly drop the expression, `std::mem::drop` conveys your intention
74- /// better and is less error-prone.
75- ///
76- /// ### Example
77- /// ```rust
78- /// # struct DroppableItem;
79- /// {
80- /// let _ = DroppableItem;
81- /// // ^ dropped here
82- /// /* more code */
83- /// }
84- /// ```
85- ///
86- /// Use instead:
87- /// ```rust
88- /// # struct DroppableItem;
89- /// {
90- /// let _droppable = DroppableItem;
91- /// /* more code */
92- /// // dropped at end of scope
93- /// }
94- /// ```
95- #[ clippy:: version = "1.50.0" ]
96- pub LET_UNDERSCORE_DROP ,
97- pedantic,
98- "non-binding let on a type that implements `Drop`"
99- }
100-
101- declare_lint_pass ! ( LetUnderscore => [ LET_UNDERSCORE_MUST_USE , LET_UNDERSCORE_LOCK , LET_UNDERSCORE_DROP ] ) ;
102-
103- const SYNC_GUARD_SYMS : [ Symbol ; 3 ] = [ sym:: MutexGuard , sym:: RwLockReadGuard , sym:: RwLockWriteGuard ] ;
62+ declare_lint_pass ! ( LetUnderscore => [ LET_UNDERSCORE_MUST_USE , LET_UNDERSCORE_LOCK ] ) ;
10463
10564const SYNC_GUARD_PATHS : [ & [ & str ] ; 3 ] = [
10665 & paths:: PARKING_LOT_MUTEX_GUARD ,
@@ -110,64 +69,43 @@ const SYNC_GUARD_PATHS: [&[&str]; 3] = [
11069
11170impl < ' tcx > LateLintPass < ' tcx > for LetUnderscore {
11271 fn check_local ( & mut self , cx : & LateContext < ' _ > , local : & Local < ' _ > ) {
113- if in_external_macro ( cx. tcx . sess , local. span ) {
114- return ;
115- }
116-
117- if_chain ! {
118- if let PatKind :: Wild = local. pat. kind;
119- if let Some ( init) = local. init;
120- then {
121- let init_ty = cx. typeck_results( ) . expr_ty( init) ;
122- let contains_sync_guard = init_ty. walk( ) . any( |inner| match inner. unpack( ) {
123- GenericArgKind :: Type ( inner_ty) => {
124- SYNC_GUARD_SYMS
125- . iter( )
126- . any( |& sym| is_type_diagnostic_item( cx, inner_ty, sym) )
127- || SYNC_GUARD_PATHS . iter( ) . any( |path| match_type( cx, inner_ty, path) )
128- } ,
129-
130- GenericArgKind :: Lifetime ( _) | GenericArgKind :: Const ( _) => false ,
131- } ) ;
132- if contains_sync_guard {
133- span_lint_and_help(
134- cx,
135- LET_UNDERSCORE_LOCK ,
136- local. span,
137- "non-binding let on a synchronization lock" ,
138- None ,
139- "consider using an underscore-prefixed named \
140- binding or dropping explicitly with `std::mem::drop`",
141- ) ;
142- } else if init_ty. needs_drop( cx. tcx, cx. param_env) {
143- span_lint_and_help(
144- cx,
145- LET_UNDERSCORE_DROP ,
146- local. span,
147- "non-binding `let` on a type that implements `Drop`" ,
148- None ,
149- "consider using an underscore-prefixed named \
72+ if !in_external_macro ( cx. tcx . sess , local. span )
73+ && let PatKind :: Wild = local. pat . kind
74+ && let Some ( init) = local. init
75+ {
76+ let init_ty = cx. typeck_results ( ) . expr_ty ( init) ;
77+ let contains_sync_guard = init_ty. walk ( ) . any ( |inner| match inner. unpack ( ) {
78+ GenericArgKind :: Type ( inner_ty) => SYNC_GUARD_PATHS . iter ( ) . any ( |path| match_type ( cx, inner_ty, path) ) ,
79+ GenericArgKind :: Lifetime ( _) | GenericArgKind :: Const ( _) => false ,
80+ } ) ;
81+ if contains_sync_guard {
82+ span_lint_and_help (
83+ cx,
84+ LET_UNDERSCORE_LOCK ,
85+ local. span ,
86+ "non-binding let on a synchronization lock" ,
87+ None ,
88+ "consider using an underscore-prefixed named \
15089 binding or dropping explicitly with `std::mem::drop`",
151- ) ;
152- } else if is_must_use_ty( cx, cx. typeck_results( ) . expr_ty( init) ) {
153- span_lint_and_help(
154- cx,
155- LET_UNDERSCORE_MUST_USE ,
156- local. span,
157- "non-binding let on an expression with `#[must_use]` type" ,
158- None ,
159- "consider explicitly using expression value" ,
160- ) ;
161- } else if is_must_use_func_call( cx, init) {
162- span_lint_and_help(
163- cx,
164- LET_UNDERSCORE_MUST_USE ,
165- local. span,
166- "non-binding let on a result of a `#[must_use]` function" ,
167- None ,
168- "consider explicitly using function result" ,
169- ) ;
170- }
90+ ) ;
91+ } else if is_must_use_ty ( cx, cx. typeck_results ( ) . expr_ty ( init) ) {
92+ span_lint_and_help (
93+ cx,
94+ LET_UNDERSCORE_MUST_USE ,
95+ local. span ,
96+ "non-binding let on an expression with `#[must_use]` type" ,
97+ None ,
98+ "consider explicitly using expression value" ,
99+ ) ;
100+ } else if is_must_use_func_call ( cx, init) {
101+ span_lint_and_help (
102+ cx,
103+ LET_UNDERSCORE_MUST_USE ,
104+ local. span ,
105+ "non-binding let on a result of a `#[must_use]` function" ,
106+ None ,
107+ "consider explicitly using function result" ,
108+ ) ;
171109 }
172110 }
173111 }
0 commit comments