11use clippy_utils:: diagnostics:: span_lint_and_help;
22use clippy_utils:: ty:: { is_must_use_ty, is_type_diagnostic_item, 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;
@@ -60,45 +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 ] ) ;
62+ declare_lint_pass ! ( LetUnderscore => [ LET_UNDERSCORE_MUST_USE , LET_UNDERSCORE_LOCK ] ) ;
10263
10364const SYNC_GUARD_SYMS : [ Symbol ; 3 ] = [ sym:: MutexGuard , sym:: RwLockReadGuard , sym:: RwLockWriteGuard ] ;
10465
@@ -110,64 +71,49 @@ const SYNC_GUARD_PATHS: [&[&str]; 3] = [
11071
11172impl < ' tcx > LateLintPass < ' tcx > for LetUnderscore {
11273 fn check_local ( & mut self , cx : & LateContext < ' _ > , local : & Local < ' _ > ) {
113- if in_external_macro ( cx. tcx . sess , local. span ) {
114- return ;
115- }
74+ if !in_external_macro ( cx. tcx . sess , local. span )
75+ && let PatKind :: Wild = local. pat . kind
76+ && let Some ( init) = local. init
77+ {
78+ let init_ty = cx. typeck_results ( ) . expr_ty ( init) ;
79+ let contains_sync_guard = init_ty. walk ( ) . any ( |inner| match inner. unpack ( ) {
80+ GenericArgKind :: Type ( inner_ty) => {
81+ SYNC_GUARD_SYMS
82+ . iter ( )
83+ . any ( |& sym| is_type_diagnostic_item ( cx, inner_ty, sym) )
84+ || SYNC_GUARD_PATHS . iter ( ) . any ( |path| match_type ( cx, inner_ty, path) )
85+ } ,
11686
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 \
87+ GenericArgKind :: Lifetime ( _) | GenericArgKind :: Const ( _) => false ,
88+ } ) ;
89+ if contains_sync_guard {
90+ span_lint_and_help (
91+ cx,
92+ LET_UNDERSCORE_LOCK ,
93+ local. span ,
94+ "non-binding let on a synchronization lock" ,
95+ None ,
96+ "consider using an underscore-prefixed named \
15097 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- }
98+ ) ;
99+ } else if is_must_use_ty ( cx, cx. typeck_results ( ) . expr_ty ( init) ) {
100+ span_lint_and_help (
101+ cx,
102+ LET_UNDERSCORE_MUST_USE ,
103+ local. span ,
104+ "non-binding let on an expression with `#[must_use]` type" ,
105+ None ,
106+ "consider explicitly using expression value" ,
107+ ) ;
108+ } else if is_must_use_func_call ( cx, init) {
109+ span_lint_and_help (
110+ cx,
111+ LET_UNDERSCORE_MUST_USE ,
112+ local. span ,
113+ "non-binding let on a result of a `#[must_use]` function" ,
114+ None ,
115+ "consider explicitly using function result" ,
116+ ) ;
171117 }
172118 }
173119 }
0 commit comments