@@ -12,8 +12,8 @@ use rustc_errors::Applicability;
1212use rustc_hir:: def_id:: DefId ;
1313use rustc_hir:: intravisit:: { InferKind , Visitor , VisitorExt , walk_ty} ;
1414use rustc_hir:: {
15- self as hir, AmbigArg , BindingMode , Body , BodyId , BorrowKind , Expr , ExprKind , HirId , MatchSource , Mutability , Node ,
16- Pat , PatKind , Path , QPath , TyKind , UnOp ,
15+ self as hir, AmbigArg , BindingMode , Body , BodyId , BorrowKind , Expr , ExprKind , HirId , Impl , Item , ItemKind ,
16+ MatchSource , Mutability , Node , Pat , PatKind , Path , QPath , TyKind , UnOp ,
1717} ;
1818use rustc_lint:: { LateContext , LateLintPass } ;
1919use rustc_middle:: ty:: adjustment:: { Adjust , Adjustment , AutoBorrow , AutoBorrowMutability } ;
@@ -169,6 +169,9 @@ pub struct Dereferencing<'tcx> {
169169 ///
170170 /// e.g. `m!(x) | Foo::Bar(ref x)`
171171 ref_locals : FxIndexMap < HirId , Option < RefPat > > ,
172+
173+ /// Whether the current context is within a `Deref` impl.
174+ in_deref_impl : bool ,
172175}
173176
174177#[ derive( Debug ) ]
@@ -246,7 +249,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
246249 // Stop processing sub expressions when a macro call is seen
247250 if expr. span . from_expansion ( ) {
248251 if let Some ( ( state, data) ) = self . state . take ( ) {
249- report ( cx, expr, state, data, cx. typeck_results ( ) ) ;
252+ report ( cx, expr, state, data, cx. typeck_results ( ) , self . in_deref_impl ) ;
250253 }
251254 return ;
252255 }
@@ -255,15 +258,15 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
255258 let Some ( ( kind, sub_expr, skip_expr) ) = try_parse_ref_op ( cx. tcx , typeck, expr) else {
256259 // The whole chain of reference operations has been seen
257260 if let Some ( ( state, data) ) = self . state . take ( ) {
258- report ( cx, expr, state, data, typeck) ;
261+ report ( cx, expr, state, data, typeck, self . in_deref_impl ) ;
259262 }
260263 return ;
261264 } ;
262265 self . skip_expr = skip_expr;
263266
264267 if is_from_proc_macro ( cx, expr) {
265268 if let Some ( ( state, data) ) = self . state . take ( ) {
266- report ( cx, expr, state, data, cx. typeck_results ( ) ) ;
269+ report ( cx, expr, state, data, cx. typeck_results ( ) , self . in_deref_impl ) ;
267270 }
268271 return ;
269272 }
@@ -515,7 +518,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
515518 ( Some ( ( State :: DerefedBorrow ( state) , data) ) , RefOp :: AddrOf ( mutability) ) => {
516519 let adjusted_ty = data. adjusted_ty ;
517520 let stability = state. stability ;
518- report ( cx, expr, State :: DerefedBorrow ( state) , data, typeck) ;
521+ report ( cx, expr, State :: DerefedBorrow ( state) , data, typeck, self . in_deref_impl ) ;
519522 if stability. is_deref_stable ( ) {
520523 self . state = Some ( (
521524 State :: Borrow { mutability } ,
@@ -530,7 +533,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
530533 let adjusted_ty = data. adjusted_ty ;
531534 let stability = state. stability ;
532535 let for_field_access = state. for_field_access ;
533- report ( cx, expr, State :: DerefedBorrow ( state) , data, typeck) ;
536+ report ( cx, expr, State :: DerefedBorrow ( state) , data, typeck, self . in_deref_impl ) ;
534537 if let Some ( name) = for_field_access
535538 && let sub_expr_ty = typeck. expr_ty ( sub_expr)
536539 && !ty_contains_field ( sub_expr_ty, name)
@@ -602,7 +605,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
602605 ) ) ;
603606 } ,
604607
605- ( Some ( ( state, data) ) , _) => report ( cx, expr, state, data, typeck) ,
608+ ( Some ( ( state, data) ) , _) => report ( cx, expr, state, data, typeck, self . in_deref_impl ) ,
606609 }
607610 }
608611
@@ -673,6 +676,31 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
673676 self . current_body = None ;
674677 }
675678 }
679+
680+ fn check_item ( & mut self , cx : & LateContext < ' _ > , item : & Item < ' _ > ) {
681+ if is_deref_impl ( cx, item) {
682+ self . in_deref_impl = true ;
683+ }
684+ }
685+
686+ fn check_item_post ( & mut self , cx : & LateContext < ' _ > , item : & Item < ' _ > ) {
687+ if is_deref_impl ( cx, item) {
688+ self . in_deref_impl = false ;
689+ }
690+ }
691+ }
692+
693+ fn is_deref_impl ( cx : & LateContext < ' _ > , item : & Item < ' _ > ) -> bool {
694+ if let ItemKind :: Impl ( Impl {
695+ of_trait : Some ( of_trait) ,
696+ ..
697+ } ) = & item. kind
698+ && let Some ( trait_id) = of_trait. trait_ref . trait_def_id ( )
699+ {
700+ cx. tcx . is_diagnostic_item ( sym:: Deref , trait_id)
701+ } else {
702+ false
703+ }
676704}
677705
678706fn try_parse_ref_op < ' tcx > (
@@ -938,13 +966,19 @@ fn report<'tcx>(
938966 state : State ,
939967 data : StateData < ' tcx > ,
940968 typeck : & ' tcx TypeckResults < ' tcx > ,
969+ in_deref_impl : bool ,
941970) {
942971 match state {
943972 State :: DerefMethod {
944973 ty_changed_count,
945974 is_ufcs,
946975 mutbl,
947976 } => {
977+ // Skip when inside implementation of the `Deref` trait.
978+ if in_deref_impl {
979+ return ;
980+ }
981+
948982 let mut app = Applicability :: MachineApplicable ;
949983 let ( expr_str, expr_is_macro_call) =
950984 snippet_with_context ( cx, expr. span , data. first_expr . span . ctxt ( ) , ".." , & mut app) ;
0 commit comments