@@ -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 > {
@@ -187,9 +174,10 @@ pub struct Dereferencing<'tcx> {
187
174
/// e.g. `m!(x) | Foo::Bar(ref x)`
188
175
ref_locals : FxIndexMap < HirId , Option < RefPat > > ,
189
176
190
- /// Map from body owners to `PossibleBorrowerMap`s. Used by `needless_borrow_impl_arg_position`
191
- /// to determine when a borrowed expression can instead be moved.
192
- possible_borrowers : FxIndexMap < LocalDefId , PossibleBorrowerMap < ' tcx , ' tcx > > ,
177
+ /// Stack of (body owner, `PossibleBorrowerMap`) pairs. Used by
178
+ /// `needless_borrow_impl_arg_position` to determine when a borrowed expression can instead
179
+ /// be moved.
180
+ possible_borrowers : Vec < ( LocalDefId , PossibleBorrowerMap < ' tcx , ' tcx > ) > ,
193
181
194
182
// `IntoIterator` for arrays requires Rust 1.53.
195
183
msrv : Option < RustcVersion > ,
@@ -571,6 +559,12 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
571
559
}
572
560
573
561
fn check_body_post ( & mut self , cx : & LateContext < ' tcx > , body : & ' tcx Body < ' _ > ) {
562
+ if self . possible_borrowers . last ( ) . map_or ( false , |& ( local_def_id, _) | {
563
+ local_def_id == cx. tcx . hir ( ) . body_owner_def_id ( body. id ( ) )
564
+ } ) {
565
+ self . possible_borrowers . pop ( ) ;
566
+ }
567
+
574
568
if Some ( body. id ( ) ) == self . current_body {
575
569
for pat in self . ref_locals . drain ( ..) . filter_map ( |( _, x) | x) {
576
570
let replacements = pat. replacements ;
@@ -703,7 +697,7 @@ impl Position {
703
697
#[ expect( clippy:: too_many_lines) ]
704
698
fn walk_parents < ' tcx > (
705
699
cx : & LateContext < ' tcx > ,
706
- possible_borrowers : & mut FxIndexMap < LocalDefId , PossibleBorrowerMap < ' tcx , ' tcx > > ,
700
+ possible_borrowers : & mut Vec < ( LocalDefId , PossibleBorrowerMap < ' tcx , ' tcx > ) > ,
707
701
e : & ' tcx Expr < ' _ > ,
708
702
msrv : Option < RustcVersion > ,
709
703
) -> ( Position , & ' tcx [ Adjustment < ' tcx > ] ) {
@@ -1061,7 +1055,7 @@ fn ty_contains_infer(ty: &hir::Ty<'_>) -> bool {
1061
1055
#[ expect( clippy:: too_many_arguments) ]
1062
1056
fn needless_borrow_impl_arg_position < ' tcx > (
1063
1057
cx : & LateContext < ' tcx > ,
1064
- possible_borrowers : & mut FxIndexMap < LocalDefId , PossibleBorrowerMap < ' tcx , ' tcx > > ,
1058
+ possible_borrowers : & mut Vec < ( LocalDefId , PossibleBorrowerMap < ' tcx , ' tcx > ) > ,
1065
1059
parent : & Expr < ' tcx > ,
1066
1060
arg_index : usize ,
1067
1061
param_ty : ParamTy ,
@@ -1202,7 +1196,7 @@ fn has_ref_mut_self_method(cx: &LateContext<'_>, trait_def_id: DefId) -> bool {
1202
1196
1203
1197
fn referent_used_exactly_once < ' a , ' tcx > (
1204
1198
cx : & ' a LateContext < ' tcx > ,
1205
- possible_borrower : & mut FxIndexMap < LocalDefId , PossibleBorrowerMap < ' tcx , ' tcx > > ,
1199
+ possible_borrowers : & mut Vec < ( LocalDefId , PossibleBorrowerMap < ' tcx , ' tcx > ) > ,
1206
1200
reference : & Expr < ' tcx > ,
1207
1201
) -> bool {
1208
1202
let mir = enclosing_mir ( cx. tcx , reference. hir_id ) ;
@@ -1213,9 +1207,13 @@ fn referent_used_exactly_once<'a, 'tcx>(
1213
1207
&& !place. has_deref ( )
1214
1208
{
1215
1209
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) ) ;
1210
+ if possible_borrowers
1211
+ . last ( )
1212
+ . map_or ( true , |& ( local_def_id, _) | local_def_id != body_owner_local_def_id)
1213
+ {
1214
+ possible_borrowers. push ( ( body_owner_local_def_id, PossibleBorrowerMap :: new ( cx, mir) ) ) ;
1215
+ }
1216
+ let possible_borrower = & mut possible_borrowers. last_mut ( ) . unwrap ( ) . 1 ;
1219
1217
// If `only_borrowers` were used here, the `copyable_iterator::warn` test would fail. The reason is
1220
1218
// that `PossibleBorrowerVisitor::visit_terminator` considers `place.local` a possible borrower of
1221
1219
// itself. See the comment in that method for an explanation as to why.
0 commit comments