1
1
use crate :: { LateContext , LateLintPass , LintContext } ;
2
2
use rustc_errors:: Applicability ;
3
3
use rustc_hir as hir;
4
- use rustc_middle:: {
5
- lint:: LintDiagnosticBuilder ,
6
- ty:: { self , Ty } ,
7
- } ;
4
+ use rustc_middle:: { lint:: LintDiagnosticBuilder , ty} ;
8
5
use rustc_span:: Symbol ;
9
6
10
7
declare_lint ! {
@@ -87,32 +84,7 @@ declare_lint! {
87
84
"non-binding let on a synchronization lock"
88
85
}
89
86
90
- declare_lint ! {
91
- /// The `let_underscore_must_use` lint checks for statements which don't bind
92
- /// a `must_use` expression to anything, causing the lock to be released
93
- /// immediately instead of at end of scope, which is typically incorrect.
94
- ///
95
- /// ### Example
96
- /// ```rust
97
- /// #[must_use]
98
- /// struct SomeStruct;
99
- ///
100
- /// fn main() {
101
- /// // SomeStuct is dropped immediately instead of at end of scope.
102
- /// let _ = SomeStruct;
103
- /// }
104
- /// ```
105
- /// ### Explanation
106
- ///
107
- /// Statements which assign an expression to an underscore causes the
108
- /// expression to immediately drop. Usually, it's better to explicitly handle
109
- /// the `must_use` expression.
110
- pub LET_UNDERSCORE_MUST_USE ,
111
- Allow ,
112
- "non-binding let on a expression marked `must_use`"
113
- }
114
-
115
- declare_lint_pass ! ( LetUnderscore => [ LET_UNDERSCORE_DROP , LET_UNDERSCORE_LOCK , LET_UNDERSCORE_MUST_USE ] ) ;
87
+ declare_lint_pass ! ( LetUnderscore => [ LET_UNDERSCORE_DROP , LET_UNDERSCORE_LOCK ] ) ;
116
88
117
89
const SYNC_GUARD_SYMBOLS : [ Symbol ; 3 ] = [
118
90
rustc_span:: sym:: MutexGuard ,
@@ -138,8 +110,6 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
138
110
. any ( |guard_symbol| cx. tcx . is_diagnostic_item ( * guard_symbol, adt. did ( ) ) ) ,
139
111
_ => false ,
140
112
} ;
141
- let is_must_use_ty = is_must_use_ty ( cx, cx. typeck_results ( ) . expr_ty ( init) ) ;
142
- let is_must_use_func_call = is_must_use_func_call ( cx, init) ;
143
113
144
114
if is_sync_lock {
145
115
cx. struct_span_lint ( LET_UNDERSCORE_LOCK , local. span , |lint| {
@@ -150,15 +120,6 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
150
120
"non-binding let on a synchronization lock" ,
151
121
)
152
122
} )
153
- } else if is_must_use_ty || is_must_use_func_call {
154
- cx. struct_span_lint ( LET_UNDERSCORE_MUST_USE , local. span , |lint| {
155
- build_and_emit_lint (
156
- lint,
157
- local,
158
- init. span ,
159
- "non-binding let on a expression marked `must_use`" ,
160
- ) ;
161
- } )
162
123
} else {
163
124
cx. struct_span_lint ( LET_UNDERSCORE_DROP , local. span , |lint| {
164
125
build_and_emit_lint (
@@ -194,65 +155,3 @@ fn build_and_emit_lint(
194
155
)
195
156
. emit ( ) ;
196
157
}
197
-
198
- // return true if `ty` is a type that is marked as `must_use`
199
- fn is_must_use_ty < ' tcx > ( cx : & LateContext < ' tcx > , ty : Ty < ' tcx > ) -> bool {
200
- match ty. kind ( ) {
201
- ty:: Adt ( adt, _) => has_must_use_attr ( cx, adt. did ( ) ) ,
202
- ty:: Foreign ( ref did) => has_must_use_attr ( cx, * did) ,
203
- ty:: Slice ( ty)
204
- | ty:: Array ( ty, _)
205
- | ty:: RawPtr ( ty:: TypeAndMut { ty, .. } )
206
- | ty:: Ref ( _, ty, _) => {
207
- // for the Array case we don't need to care for the len == 0 case
208
- // because we don't want to lint functions returning empty arrays
209
- is_must_use_ty ( cx, * ty)
210
- }
211
- ty:: Tuple ( substs) => substs. iter ( ) . any ( |ty| is_must_use_ty ( cx, ty) ) ,
212
- ty:: Opaque ( ref def_id, _) => {
213
- for ( predicate, _) in cx. tcx . explicit_item_bounds ( * def_id) {
214
- if let ty:: PredicateKind :: Trait ( trait_predicate) = predicate. kind ( ) . skip_binder ( ) {
215
- if has_must_use_attr ( cx, trait_predicate. trait_ref . def_id ) {
216
- return true ;
217
- }
218
- }
219
- }
220
- false
221
- }
222
- ty:: Dynamic ( binder, _) => {
223
- for predicate in binder. iter ( ) {
224
- if let ty:: ExistentialPredicate :: Trait ( ref trait_ref) = predicate. skip_binder ( ) {
225
- if has_must_use_attr ( cx, trait_ref. def_id ) {
226
- return true ;
227
- }
228
- }
229
- }
230
- false
231
- }
232
- _ => false ,
233
- }
234
- }
235
-
236
- // check if expr is calling method or function with #[must_use] attribute
237
- fn is_must_use_func_call ( cx : & LateContext < ' _ > , expr : & hir:: Expr < ' _ > ) -> bool {
238
- let did = match expr. kind {
239
- hir:: ExprKind :: Call ( path, _) if let hir:: ExprKind :: Path ( ref qpath) = path. kind => {
240
- if let hir:: def:: Res :: Def ( _, did) = cx. qpath_res ( qpath, path. hir_id ) {
241
- Some ( did)
242
- } else {
243
- None
244
- }
245
- } ,
246
- hir:: ExprKind :: MethodCall ( ..) => {
247
- cx. typeck_results ( ) . type_dependent_def_id ( expr. hir_id )
248
- }
249
- _ => None ,
250
- } ;
251
-
252
- did. map_or ( false , |did| has_must_use_attr ( cx, did) )
253
- }
254
-
255
- // returns true if DefId contains a `#[must_use]` attribute
256
- fn has_must_use_attr ( cx : & LateContext < ' _ > , did : hir:: def_id:: DefId ) -> bool {
257
- cx. tcx . has_attr ( did, rustc_span:: sym:: must_use)
258
- }
0 commit comments