@@ -20,16 +20,15 @@ use rustc_hir::{
20
20
} ;
21
21
use rustc_index:: bit_set:: BitSet ;
22
22
use rustc_infer:: infer:: TyCtxtInferExt ;
23
- use rustc_lint:: { LateContext , LateLintPass , LintArray , LintPass } ;
24
- use rustc_lint_defs:: lint_array;
23
+ use rustc_lint:: { LateContext , LateLintPass } ;
25
24
use rustc_middle:: mir:: { Rvalue , StatementKind } ;
26
25
use rustc_middle:: ty:: adjustment:: { Adjust , Adjustment , AutoBorrow , AutoBorrowMutability } ;
27
26
use rustc_middle:: ty:: {
28
27
self , Binder , BoundVariableKind , EarlyBinder , FnSig , GenericArgKind , List , ParamTy , PredicateKind ,
29
28
ProjectionPredicate , Ty , TyCtxt , TypeVisitable , TypeckResults ,
30
29
} ;
31
30
use rustc_semver:: RustcVersion ;
32
- use rustc_session:: declare_tool_lint;
31
+ use rustc_session:: { declare_tool_lint, impl_lint_pass } ;
33
32
use rustc_span:: { symbol:: sym, Span , Symbol , DUMMY_SP } ;
34
33
use rustc_trait_selection:: infer:: InferCtxtExt as _;
35
34
use rustc_trait_selection:: traits:: { query:: evaluate_obligation:: InferCtxtExt as _, Obligation , ObligationCause } ;
@@ -146,24 +145,12 @@ declare_clippy_lint! {
146
145
"dereferencing when the compiler would automatically dereference"
147
146
}
148
147
149
- #[ expect( rustc:: internal) ]
150
- impl < ' tcx > LintPass for Dereferencing < ' tcx > {
151
- fn name ( & self ) -> & ' static str {
152
- stringify ! ( $ty)
153
- }
154
- }
155
-
156
- impl < ' tcx > Dereferencing < ' tcx > {
157
- #[ expect( dead_code) ]
158
- pub fn get_lints ( ) -> LintArray {
159
- lint_array ! (
160
- EXPLICIT_DEREF_METHODS ,
161
- NEEDLESS_BORROW ,
162
- REF_BINDING_TO_REFERENCE ,
163
- EXPLICIT_AUTO_DEREF ,
164
- )
165
- }
166
- }
148
+ impl_lint_pass ! ( Dereferencing <' _> => [
149
+ EXPLICIT_DEREF_METHODS ,
150
+ NEEDLESS_BORROW ,
151
+ REF_BINDING_TO_REFERENCE ,
152
+ EXPLICIT_AUTO_DEREF ,
153
+ ] ) ;
167
154
168
155
#[ derive( Default ) ]
169
156
pub struct Dereferencing < ' tcx > {
@@ -189,7 +176,7 @@ pub struct Dereferencing<'tcx> {
189
176
190
177
/// Map from body owners to `PossibleBorrowerMap`s. Used by `needless_borrow_impl_arg_position`
191
178
/// to determine when a borrowed expression can instead be moved.
192
- possible_borrowers : FxIndexMap < LocalDefId , PossibleBorrowerMap < ' tcx , ' tcx > > ,
179
+ possible_borrowers : Vec < ( LocalDefId , PossibleBorrowerMap < ' tcx , ' tcx > ) > ,
193
180
194
181
// `IntoIterator` for arrays requires Rust 1.53.
195
182
msrv : Option < RustcVersion > ,
@@ -571,6 +558,12 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
571
558
}
572
559
573
560
fn check_body_post ( & mut self , cx : & LateContext < ' tcx > , body : & ' tcx Body < ' _ > ) {
561
+ if self . possible_borrowers . last ( ) . map_or ( false , |& ( local_def_id, _) | {
562
+ local_def_id == cx. tcx . hir ( ) . body_owner_def_id ( body. id ( ) )
563
+ } ) {
564
+ self . possible_borrowers . pop ( ) ;
565
+ }
566
+
574
567
if Some ( body. id ( ) ) == self . current_body {
575
568
for pat in self . ref_locals . drain ( ..) . filter_map ( |( _, x) | x) {
576
569
let replacements = pat. replacements ;
@@ -703,7 +696,7 @@ impl Position {
703
696
#[ expect( clippy:: too_many_lines) ]
704
697
fn walk_parents < ' tcx > (
705
698
cx : & LateContext < ' tcx > ,
706
- possible_borrowers : & mut FxIndexMap < LocalDefId , PossibleBorrowerMap < ' tcx , ' tcx > > ,
699
+ possible_borrowers : & mut Vec < ( LocalDefId , PossibleBorrowerMap < ' tcx , ' tcx > ) > ,
707
700
e : & ' tcx Expr < ' _ > ,
708
701
msrv : Option < RustcVersion > ,
709
702
) -> ( Position , & ' tcx [ Adjustment < ' tcx > ] ) {
@@ -1061,7 +1054,7 @@ fn ty_contains_infer(ty: &hir::Ty<'_>) -> bool {
1061
1054
#[ expect( clippy:: too_many_arguments) ]
1062
1055
fn needless_borrow_impl_arg_position < ' tcx > (
1063
1056
cx : & LateContext < ' tcx > ,
1064
- possible_borrowers : & mut FxIndexMap < LocalDefId , PossibleBorrowerMap < ' tcx , ' tcx > > ,
1057
+ possible_borrowers : & mut Vec < ( LocalDefId , PossibleBorrowerMap < ' tcx , ' tcx > ) > ,
1065
1058
parent : & Expr < ' tcx > ,
1066
1059
arg_index : usize ,
1067
1060
param_ty : ParamTy ,
@@ -1202,7 +1195,7 @@ fn has_ref_mut_self_method(cx: &LateContext<'_>, trait_def_id: DefId) -> bool {
1202
1195
1203
1196
fn referent_used_exactly_once < ' a , ' tcx > (
1204
1197
cx : & ' a LateContext < ' tcx > ,
1205
- possible_borrower : & mut FxIndexMap < LocalDefId , PossibleBorrowerMap < ' tcx , ' tcx > > ,
1198
+ possible_borrowers : & mut Vec < ( LocalDefId , PossibleBorrowerMap < ' tcx , ' tcx > ) > ,
1206
1199
reference : & Expr < ' tcx > ,
1207
1200
) -> bool {
1208
1201
let mir = enclosing_mir ( cx. tcx , reference. hir_id ) ;
@@ -1213,9 +1206,13 @@ fn referent_used_exactly_once<'a, 'tcx>(
1213
1206
&& !place. has_deref ( )
1214
1207
{
1215
1208
let body_owner_local_def_id = cx. tcx . hir ( ) . enclosing_body_owner ( reference. hir_id ) ;
1216
- let possible_borrower = possible_borrower
1217
- . entry ( body_owner_local_def_id)
1218
- . or_insert_with ( || PossibleBorrowerMap :: new ( cx, mir) ) ;
1209
+ if possible_borrowers
1210
+ . last ( )
1211
+ . map_or ( true , |& ( local_def_id, _) | local_def_id != body_owner_local_def_id)
1212
+ {
1213
+ possible_borrowers. push ( ( body_owner_local_def_id, PossibleBorrowerMap :: new ( cx, mir) ) ) ;
1214
+ }
1215
+ let possible_borrower = & mut possible_borrowers. last_mut ( ) . unwrap ( ) . 1 ;
1219
1216
// If `only_borrowers` were used here, the `copyable_iterator::warn` test would fail. The reason is
1220
1217
// that `PossibleBorrowerVisitor::visit_terminator` considers `place.local` a possible borrower of
1221
1218
// itself. See the comment in that method for an explanation as to why.
0 commit comments