@@ -20,16 +20,15 @@ use rustc_hir::{
2020} ;
2121use rustc_index:: bit_set:: BitSet ;
2222use 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 } ;
2524use rustc_middle:: mir:: { Rvalue , StatementKind } ;
2625use rustc_middle:: ty:: adjustment:: { Adjust , Adjustment , AutoBorrow , AutoBorrowMutability } ;
2726use rustc_middle:: ty:: {
2827 self , Binder , BoundVariableKind , EarlyBinder , FnSig , GenericArgKind , List , ParamTy , PredicateKind ,
2928 ProjectionPredicate , Ty , TyCtxt , TypeVisitable , TypeckResults ,
3029} ;
3130use rustc_semver:: RustcVersion ;
32- use rustc_session:: declare_tool_lint;
31+ use rustc_session:: { declare_tool_lint, impl_lint_pass } ;
3332use rustc_span:: { symbol:: sym, Span , Symbol , DUMMY_SP } ;
3433use rustc_trait_selection:: infer:: InferCtxtExt as _;
3534use rustc_trait_selection:: traits:: { query:: evaluate_obligation:: InferCtxtExt as _, Obligation , ObligationCause } ;
@@ -146,24 +145,12 @@ declare_clippy_lint! {
146145 "dereferencing when the compiler would automatically dereference"
147146}
148147
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+ ] ) ;
167154
168155#[ derive( Default ) ]
169156pub struct Dereferencing < ' tcx > {
@@ -187,9 +174,10 @@ pub struct Dereferencing<'tcx> {
187174 /// e.g. `m!(x) | Foo::Bar(ref x)`
188175 ref_locals : FxIndexMap < HirId , Option < RefPat > > ,
189176
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 > ) > ,
193181
194182 // `IntoIterator` for arrays requires Rust 1.53.
195183 msrv : Option < RustcVersion > ,
@@ -571,6 +559,12 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
571559 }
572560
573561 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+
574568 if Some ( body. id ( ) ) == self . current_body {
575569 for pat in self . ref_locals . drain ( ..) . filter_map ( |( _, x) | x) {
576570 let replacements = pat. replacements ;
@@ -703,7 +697,7 @@ impl Position {
703697#[ expect( clippy:: too_many_lines) ]
704698fn walk_parents < ' tcx > (
705699 cx : & LateContext < ' tcx > ,
706- possible_borrowers : & mut FxIndexMap < LocalDefId , PossibleBorrowerMap < ' tcx , ' tcx > > ,
700+ possible_borrowers : & mut Vec < ( LocalDefId , PossibleBorrowerMap < ' tcx , ' tcx > ) > ,
707701 e : & ' tcx Expr < ' _ > ,
708702 msrv : Option < RustcVersion > ,
709703) -> ( Position , & ' tcx [ Adjustment < ' tcx > ] ) {
@@ -1061,7 +1055,7 @@ fn ty_contains_infer(ty: &hir::Ty<'_>) -> bool {
10611055#[ expect( clippy:: too_many_arguments) ]
10621056fn needless_borrow_impl_arg_position < ' tcx > (
10631057 cx : & LateContext < ' tcx > ,
1064- possible_borrowers : & mut FxIndexMap < LocalDefId , PossibleBorrowerMap < ' tcx , ' tcx > > ,
1058+ possible_borrowers : & mut Vec < ( LocalDefId , PossibleBorrowerMap < ' tcx , ' tcx > ) > ,
10651059 parent : & Expr < ' tcx > ,
10661060 arg_index : usize ,
10671061 param_ty : ParamTy ,
@@ -1202,7 +1196,7 @@ fn has_ref_mut_self_method(cx: &LateContext<'_>, trait_def_id: DefId) -> bool {
12021196
12031197fn referent_used_exactly_once < ' a , ' tcx > (
12041198 cx : & ' a LateContext < ' tcx > ,
1205- possible_borrower : & mut FxIndexMap < LocalDefId , PossibleBorrowerMap < ' tcx , ' tcx > > ,
1199+ possible_borrowers : & mut Vec < ( LocalDefId , PossibleBorrowerMap < ' tcx , ' tcx > ) > ,
12061200 reference : & Expr < ' tcx > ,
12071201) -> bool {
12081202 let mir = enclosing_mir ( cx. tcx , reference. hir_id ) ;
@@ -1213,9 +1207,13 @@ fn referent_used_exactly_once<'a, 'tcx>(
12131207 && !place. has_deref ( )
12141208 {
12151209 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 ;
12191217 // If `only_borrowers` were used here, the `copyable_iterator::warn` test would fail. The reason is
12201218 // that `PossibleBorrowerVisitor::visit_terminator` considers `place.local` a possible borrower of
12211219 // itself. See the comment in that method for an explanation as to why.
0 commit comments