1
1
use clippy_utils:: diagnostics:: span_lint_and_then;
2
2
use clippy_utils:: source:: { indent_of, snippet} ;
3
3
use clippy_utils:: { expr_or_init, get_attr, path_to_local, peel_hir_expr_unary} ;
4
- use rustc_data_structures:: fx:: { FxHashMap , FxHashSet , FxIndexMap } ;
4
+ use rustc_data_structures:: fx:: { FxHashMap , FxIndexMap } ;
5
5
use rustc_errors:: Applicability ;
6
6
use rustc_hir:: def:: { DefKind , Res } ;
7
7
use rustc_hir:: intravisit:: { walk_expr, Visitor } ;
@@ -12,6 +12,7 @@ use rustc_session::impl_lint_pass;
12
12
use rustc_span:: symbol:: Ident ;
13
13
use rustc_span:: { sym, Span , DUMMY_SP } ;
14
14
use std:: borrow:: Cow ;
15
+ use std:: collections:: hash_map:: Entry ;
15
16
16
17
declare_clippy_lint ! {
17
18
/// ### What it does
@@ -57,7 +58,6 @@ impl_lint_pass!(SignificantDropTightening<'_> => [SIGNIFICANT_DROP_TIGHTENING]);
57
58
pub struct SignificantDropTightening < ' tcx > {
58
59
apas : FxIndexMap < HirId , AuxParamsAttr > ,
59
60
/// Auxiliary structure used to avoid having to verify the same type multiple times.
60
- seen_types : FxHashSet < Ty < ' tcx > > ,
61
61
type_cache : FxHashMap < Ty < ' tcx > , bool > ,
62
62
}
63
63
@@ -74,7 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for SignificantDropTightening<'tcx> {
74
74
self . apas . clear ( ) ;
75
75
let initial_dummy_stmt = dummy_stmt_expr ( body. value ) ;
76
76
let mut ap = AuxParams :: new ( & mut self . apas , & initial_dummy_stmt) ;
77
- StmtsChecker :: new ( & mut ap, cx, & mut self . seen_types , & mut self . type_cache ) . visit_body ( body) ;
77
+ StmtsChecker :: new ( & mut ap, cx, & mut self . type_cache ) . visit_body ( body) ;
78
78
for apa in ap. apas . values ( ) {
79
79
if apa. counter <= 1 || !apa. has_expensive_expr_after_last_attr {
80
80
continue ;
@@ -142,28 +142,25 @@ impl<'tcx> LateLintPass<'tcx> for SignificantDropTightening<'tcx> {
142
142
/// Checks the existence of the `#[has_significant_drop]` attribute.
143
143
struct AttrChecker < ' cx , ' others , ' tcx > {
144
144
cx : & ' cx LateContext < ' tcx > ,
145
- seen_types : & ' others mut FxHashSet < Ty < ' tcx > > ,
146
145
type_cache : & ' others mut FxHashMap < Ty < ' tcx > , bool > ,
147
146
}
148
147
149
148
impl < ' cx , ' others , ' tcx > AttrChecker < ' cx , ' others , ' tcx > {
150
- pub ( crate ) fn new (
151
- cx : & ' cx LateContext < ' tcx > ,
152
- seen_types : & ' others mut FxHashSet < Ty < ' tcx > > ,
153
- type_cache : & ' others mut FxHashMap < Ty < ' tcx > , bool > ,
154
- ) -> Self {
155
- seen_types. clear ( ) ;
156
- Self {
157
- cx,
158
- seen_types,
159
- type_cache,
160
- }
149
+ pub ( crate ) fn new ( cx : & ' cx LateContext < ' tcx > , type_cache : & ' others mut FxHashMap < Ty < ' tcx > , bool > ) -> Self {
150
+ Self { cx, type_cache }
161
151
}
162
152
163
153
fn has_sig_drop_attr ( & mut self , ty : Ty < ' tcx > ) -> bool {
164
- // The borrow checker prevents us from using something fancier like or_insert_with.
165
- if let Some ( ty) = self . type_cache . get ( & ty) {
166
- return * ty;
154
+ let ty = self
155
+ . cx
156
+ . tcx
157
+ . try_normalize_erasing_regions ( self . cx . param_env , ty)
158
+ . unwrap_or ( ty) ;
159
+ match self . type_cache . entry ( ty) {
160
+ Entry :: Occupied ( e) => return * e. get ( ) ,
161
+ Entry :: Vacant ( e) => {
162
+ e. insert ( false ) ;
163
+ } ,
167
164
}
168
165
let value = self . has_sig_drop_attr_uncached ( ty) ;
169
166
self . type_cache . insert ( ty, value) ;
@@ -185,7 +182,7 @@ impl<'cx, 'others, 'tcx> AttrChecker<'cx, 'others, 'tcx> {
185
182
rustc_middle:: ty:: Adt ( a, b) => {
186
183
for f in a. all_fields ( ) {
187
184
let ty = f. ty ( self . cx . tcx , b) ;
188
- if ! self . has_seen_ty ( ty ) && self . has_sig_drop_attr ( ty) {
185
+ if self . has_sig_drop_attr ( ty) {
189
186
return true ;
190
187
}
191
188
}
@@ -205,32 +202,21 @@ impl<'cx, 'others, 'tcx> AttrChecker<'cx, 'others, 'tcx> {
205
202
_ => false ,
206
203
}
207
204
}
208
-
209
- fn has_seen_ty ( & mut self , ty : Ty < ' tcx > ) -> bool {
210
- !self . seen_types . insert ( ty)
211
- }
212
205
}
213
206
214
207
struct StmtsChecker < ' ap , ' lc , ' others , ' stmt , ' tcx > {
215
208
ap : & ' ap mut AuxParams < ' others , ' stmt , ' tcx > ,
216
209
cx : & ' lc LateContext < ' tcx > ,
217
- seen_types : & ' others mut FxHashSet < Ty < ' tcx > > ,
218
210
type_cache : & ' others mut FxHashMap < Ty < ' tcx > , bool > ,
219
211
}
220
212
221
213
impl < ' ap , ' lc , ' others , ' stmt , ' tcx > StmtsChecker < ' ap , ' lc , ' others , ' stmt , ' tcx > {
222
214
fn new (
223
215
ap : & ' ap mut AuxParams < ' others , ' stmt , ' tcx > ,
224
216
cx : & ' lc LateContext < ' tcx > ,
225
- seen_types : & ' others mut FxHashSet < Ty < ' tcx > > ,
226
217
type_cache : & ' others mut FxHashMap < Ty < ' tcx > , bool > ,
227
218
) -> Self {
228
- Self {
229
- ap,
230
- cx,
231
- seen_types,
232
- type_cache,
233
- }
219
+ Self { ap, cx, type_cache }
234
220
}
235
221
236
222
fn manage_has_expensive_expr_after_last_attr ( & mut self ) {
@@ -288,7 +274,7 @@ impl<'ap, 'lc, 'others, 'stmt, 'tcx> Visitor<'tcx> for StmtsChecker<'ap, 'lc, 'o
288
274
apa. counter = apa. counter . wrapping_add ( 1 ) ;
289
275
apa. has_expensive_expr_after_last_attr = false ;
290
276
} ;
291
- let mut ac = AttrChecker :: new ( self . cx , self . seen_types , self . type_cache ) ;
277
+ let mut ac = AttrChecker :: new ( self . cx , self . type_cache ) ;
292
278
if ac. has_sig_drop_attr ( self . cx . typeck_results ( ) . expr_ty ( expr) ) {
293
279
if let hir:: StmtKind :: Let ( local) = self . ap . curr_stmt . kind
294
280
&& let hir:: PatKind :: Binding ( _, hir_id, ident, _) = local. pat . kind
0 commit comments