@@ -15,7 +15,7 @@ use rustc_lint::{LateContext, LateLintPass};
15
15
use rustc_middle:: ty:: adjustment:: { Adjust , Adjustment , AutoBorrow , AutoBorrowMutability } ;
16
16
use rustc_middle:: ty:: { self , Ty , TyCtxt , TypeFoldable , TypeckResults } ;
17
17
use rustc_session:: { declare_tool_lint, impl_lint_pass} ;
18
- use rustc_span:: { symbol:: sym, Span , Symbol } ;
18
+ use rustc_span:: { symbol:: sym, Span , Symbol , SyntaxContext } ;
19
19
20
20
declare_clippy_lint ! {
21
21
/// ### What it does
@@ -244,23 +244,22 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing {
244
244
245
245
match ( self . state . take ( ) , kind) {
246
246
( None , kind) => {
247
- let parent = get_parent_node ( cx. tcx , expr. hir_id ) ;
248
247
let expr_ty = typeck. expr_ty ( expr) ;
248
+ let ( position, parent_ctxt) = get_expr_position ( cx, expr) ;
249
249
match kind {
250
250
RefOp :: Deref => {
251
- if let Some ( Node :: Expr ( e) ) = parent
252
- && let ExprKind :: Field ( _, name) = e. kind
253
- && !ty_contains_field ( typeck. expr_ty ( sub_expr) , name. name )
251
+ if let Position :: FieldAccess ( name) = position
252
+ && !ty_contains_field ( typeck. expr_ty ( sub_expr) , name)
254
253
{
255
254
self . state = Some ( (
256
- State :: ExplicitDerefField { name : name . name } ,
255
+ State :: ExplicitDerefField { name } ,
257
256
StateData { span : expr. span , hir_id : expr. hir_id } ,
258
257
) ) ;
259
258
}
260
259
}
261
260
RefOp :: Method ( target_mut)
262
261
if !is_lint_allowed ( cx, EXPLICIT_DEREF_METHODS , expr. hir_id )
263
- && is_linted_explicit_deref_position ( parent , expr . hir_id , expr. span ) =>
262
+ && ( position . lint_explicit_deref ( ) || parent_ctxt != expr. span . ctxt ( ) ) =>
264
263
{
265
264
self . state = Some ( (
266
265
State :: DerefMethod {
@@ -322,8 +321,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing {
322
321
"this expression creates a reference which is immediately dereferenced by the compiler" ;
323
322
let borrow_msg = "this expression borrows a value the compiler would automatically borrow" ;
324
323
325
- let ( required_refs, required_precedence, msg) = if is_auto_borrow_position ( parent, expr. hir_id )
326
- {
324
+ let ( required_refs, required_precedence, msg) = if position. can_auto_borrow ( ) {
327
325
( 1 , PREC_POSTFIX , if deref_count == 1 { borrow_msg } else { deref_msg } )
328
326
} else if let Some ( & Adjust :: Borrow ( AutoBorrow :: Ref ( _, mutability) ) ) =
329
327
next_adjust. map ( |a| & a. kind )
@@ -573,60 +571,41 @@ fn deref_method_same_type<'tcx>(result_ty: Ty<'tcx>, arg_ty: Ty<'tcx>) -> bool {
573
571
}
574
572
}
575
573
576
- // Checks whether the parent node is a suitable context for switching from a deref method to the
577
- // deref operator.
578
- fn is_linted_explicit_deref_position ( parent : Option < Node < ' _ > > , child_id : HirId , child_span : Span ) -> bool {
579
- let parent = match parent {
580
- Some ( Node :: Expr ( e) ) if e. span . ctxt ( ) == child_span. ctxt ( ) => e,
581
- _ => return true ,
582
- } ;
583
- match parent. kind {
584
- // Leave deref calls in the middle of a method chain.
585
- // e.g. x.deref().foo()
586
- ExprKind :: MethodCall ( _, [ self_arg, ..] , _) if self_arg. hir_id == child_id => false ,
587
-
588
- // Leave deref calls resulting in a called function
589
- // e.g. (x.deref())()
590
- ExprKind :: Call ( func_expr, _) if func_expr. hir_id == child_id => false ,
574
+ #[ derive( Clone , Copy ) ]
575
+ enum Position {
576
+ MethodReceiver ,
577
+ FieldAccess ( Symbol ) ,
578
+ Callee ,
579
+ Postfix ,
580
+ Deref ,
581
+ Other ,
582
+ }
583
+ impl Position {
584
+ fn can_auto_borrow ( self ) -> bool {
585
+ matches ! ( self , Self :: MethodReceiver | Self :: FieldAccess ( _) | Self :: Callee )
586
+ }
591
587
592
- // Makes an ugly suggestion
593
- // e.g. *x.deref() => *&*x
594
- ExprKind :: Unary ( UnOp :: Deref , _)
595
- // Postfix expressions would require parens
596
- | ExprKind :: Match ( _, _, MatchSource :: TryDesugar | MatchSource :: AwaitDesugar )
597
- | ExprKind :: Field ( ..)
598
- | ExprKind :: Index ( ..)
599
- | ExprKind :: Err => false ,
588
+ fn lint_explicit_deref ( self ) -> bool {
589
+ matches ! ( self , Self :: Other )
590
+ }
591
+ }
600
592
601
- ExprKind :: Box ( ..)
602
- | ExprKind :: ConstBlock ( ..)
603
- | ExprKind :: Array ( _)
604
- | ExprKind :: Call ( ..)
605
- | ExprKind :: MethodCall ( ..)
606
- | ExprKind :: Tup ( ..)
607
- | ExprKind :: Binary ( ..)
608
- | ExprKind :: Unary ( ..)
609
- | ExprKind :: Lit ( ..)
610
- | ExprKind :: Cast ( ..)
611
- | ExprKind :: Type ( ..)
612
- | ExprKind :: DropTemps ( ..)
613
- | ExprKind :: If ( ..)
614
- | ExprKind :: Loop ( ..)
615
- | ExprKind :: Match ( ..)
616
- | ExprKind :: Let ( ..)
617
- | ExprKind :: Closure { ..}
618
- | ExprKind :: Block ( ..)
619
- | ExprKind :: Assign ( ..)
620
- | ExprKind :: AssignOp ( ..)
621
- | ExprKind :: Path ( ..)
622
- | ExprKind :: AddrOf ( ..)
623
- | ExprKind :: Break ( ..)
624
- | ExprKind :: Continue ( ..)
625
- | ExprKind :: Ret ( ..)
626
- | ExprKind :: InlineAsm ( ..)
627
- | ExprKind :: Struct ( ..)
628
- | ExprKind :: Repeat ( ..)
629
- | ExprKind :: Yield ( ..) => true ,
593
+ /// Get which position an expression is in relative to it's parent.
594
+ fn get_expr_position ( cx : & LateContext < ' _ > , e : & Expr < ' _ > ) -> ( Position , SyntaxContext ) {
595
+ if let Some ( Node :: Expr ( parent) ) = get_parent_node ( cx. tcx , e. hir_id ) {
596
+ let pos = match parent. kind {
597
+ ExprKind :: MethodCall ( _, [ self_arg, ..] , _) if self_arg. hir_id == e. hir_id => Position :: MethodReceiver ,
598
+ ExprKind :: Field ( _, name) => Position :: FieldAccess ( name. name ) ,
599
+ ExprKind :: Call ( f, _) if f. hir_id == e. hir_id => Position :: Callee ,
600
+ ExprKind :: Unary ( UnOp :: Deref , _) => Position :: Deref ,
601
+ ExprKind :: Match ( _, _, MatchSource :: TryDesugar | MatchSource :: AwaitDesugar ) | ExprKind :: Index ( ..) => {
602
+ Position :: Postfix
603
+ } ,
604
+ _ => Position :: Other ,
605
+ } ;
606
+ ( pos, parent. span . ctxt ( ) )
607
+ } else {
608
+ ( Position :: Other , SyntaxContext :: root ( ) )
630
609
}
631
610
}
632
611
@@ -748,20 +727,6 @@ fn walk_parents<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> (AutoDerefSt
748
727
( stability, adjustments)
749
728
}
750
729
751
- /// Checks if the given expression is a position which can auto-borrow.
752
- fn is_auto_borrow_position ( parent : Option < Node < ' _ > > , child_id : HirId ) -> bool {
753
- if let Some ( Node :: Expr ( parent) ) = parent {
754
- match parent. kind {
755
- // ExprKind::MethodCall(_, [self_arg, ..], _) => self_arg.hir_id == child_id,
756
- ExprKind :: Field ( ..) => true ,
757
- ExprKind :: Call ( f, _) => f. hir_id == child_id,
758
- _ => false ,
759
- }
760
- } else {
761
- false
762
- }
763
- }
764
-
765
730
// Checks the stability of auto-deref when assigned to a binding with the given explicit type.
766
731
//
767
732
// e.g.
0 commit comments