1
1
use clippy_utils:: diagnostics:: span_lint_and_help;
2
2
use clippy_utils:: ty:: { is_must_use_ty, is_type_diagnostic_item, match_type} ;
3
3
use clippy_utils:: { is_must_use_func_call, paths} ;
4
- use if_chain:: if_chain;
5
4
use rustc_hir:: { Local , PatKind } ;
6
5
use rustc_lint:: { LateContext , LateLintPass } ;
7
6
use rustc_middle:: lint:: in_external_macro;
@@ -60,45 +59,7 @@ declare_clippy_lint! {
60
59
"non-binding let on a synchronization lock"
61
60
}
62
61
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 ] ) ;
102
63
103
64
const SYNC_GUARD_SYMS : [ Symbol ; 3 ] = [ sym:: MutexGuard , sym:: RwLockReadGuard , sym:: RwLockWriteGuard ] ;
104
65
@@ -110,64 +71,49 @@ const SYNC_GUARD_PATHS: [&[&str]; 3] = [
110
71
111
72
impl < ' tcx > LateLintPass < ' tcx > for LetUnderscore {
112
73
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
+ } ,
116
86
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 \
150
97
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
+ ) ;
171
117
}
172
118
}
173
119
}
0 commit comments