@@ -37,83 +37,75 @@ declare_lint_pass!(NeedlessBorrowedRef => [NEEDLESS_BORROWED_REFERENCE]);
3737
3838impl < ' tcx > LateLintPass < ' tcx > for NeedlessBorrowedRef {
3939 fn check_pat ( & mut self , cx : & LateContext < ' tcx > , ref_pat : & ' tcx Pat < ' _ > ) {
40- if ref_pat. span . from_expansion ( ) {
41- // OK, simple enough, lints doesn't check in macro.
42- return ;
43- }
44-
45- // Do not lint patterns that are part of an OR `|` pattern, the binding mode must match in all arms
46- for ( _, node) in cx. tcx . hir ( ) . parent_iter ( ref_pat. hir_id ) {
47- let Node :: Pat ( pat) = node else { break } ;
48-
49- if matches ! ( pat. kind, PatKind :: Or ( _) ) {
50- return ;
40+ if let PatKind :: Ref ( pat, Mutability :: Not ) = ref_pat. kind
41+ && !ref_pat. span . from_expansion ( )
42+ && cx
43+ . tcx
44+ . hir ( )
45+ . parent_iter ( ref_pat. hir_id )
46+ . map_while ( |( _, parent) | if let Node :: Pat ( pat) = parent { Some ( pat) } else { None } )
47+ // Do not lint patterns that are part of an OR `|` pattern, the binding mode must match in all arms
48+ . all ( |pat| !matches ! ( pat. kind, PatKind :: Or ( _) ) )
49+ {
50+ match pat. kind {
51+ // Check sub_pat got a `ref` keyword (excluding `ref mut`).
52+ PatKind :: Binding ( BindingMode :: REF , _, ident, None ) => {
53+ span_lint_and_then (
54+ cx,
55+ NEEDLESS_BORROWED_REFERENCE ,
56+ ref_pat. span ,
57+ "this pattern takes a reference on something that is being dereferenced" ,
58+ |diag| {
59+ // `&ref ident`
60+ // ^^^^^
61+ let span = ref_pat. span . until ( ident. span ) ;
62+ diag. span_suggestion_verbose (
63+ span,
64+ "try removing the `&ref` part" ,
65+ String :: new ( ) ,
66+ Applicability :: MachineApplicable ,
67+ ) ;
68+ } ,
69+ ) ;
70+ } ,
71+ // Slices where each element is `ref`: `&[ref a, ref b, ..., ref z]`
72+ PatKind :: Slice (
73+ before,
74+ None
75+ | Some ( Pat {
76+ kind : PatKind :: Wild , ..
77+ } ) ,
78+ after,
79+ ) => {
80+ check_subpatterns (
81+ cx,
82+ "dereferencing a slice pattern where every element takes a reference" ,
83+ ref_pat,
84+ pat,
85+ itertools:: chain ( before, after) ,
86+ ) ;
87+ } ,
88+ PatKind :: Tuple ( subpatterns, _) | PatKind :: TupleStruct ( _, subpatterns, _) => {
89+ check_subpatterns (
90+ cx,
91+ "dereferencing a tuple pattern where every element takes a reference" ,
92+ ref_pat,
93+ pat,
94+ subpatterns,
95+ ) ;
96+ } ,
97+ PatKind :: Struct ( _, fields, _) => {
98+ check_subpatterns (
99+ cx,
100+ "dereferencing a struct pattern where every field's pattern takes a reference" ,
101+ ref_pat,
102+ pat,
103+ fields. iter ( ) . map ( |field| field. pat ) ,
104+ ) ;
105+ } ,
106+ _ => { } ,
51107 }
52108 }
53-
54- // Only lint immutable refs, because `&mut ref T` may be useful.
55- let PatKind :: Ref ( pat, Mutability :: Not ) = ref_pat. kind else {
56- return ;
57- } ;
58-
59- match pat. kind {
60- // Check sub_pat got a `ref` keyword (excluding `ref mut`).
61- PatKind :: Binding ( BindingMode :: REF , _, ident, None ) => {
62- span_lint_and_then (
63- cx,
64- NEEDLESS_BORROWED_REFERENCE ,
65- ref_pat. span ,
66- "this pattern takes a reference on something that is being dereferenced" ,
67- |diag| {
68- // `&ref ident`
69- // ^^^^^
70- let span = ref_pat. span . until ( ident. span ) ;
71- diag. span_suggestion_verbose (
72- span,
73- "try removing the `&ref` part" ,
74- String :: new ( ) ,
75- Applicability :: MachineApplicable ,
76- ) ;
77- } ,
78- ) ;
79- } ,
80- // Slices where each element is `ref`: `&[ref a, ref b, ..., ref z]`
81- PatKind :: Slice (
82- before,
83- None
84- | Some ( Pat {
85- kind : PatKind :: Wild , ..
86- } ) ,
87- after,
88- ) => {
89- check_subpatterns (
90- cx,
91- "dereferencing a slice pattern where every element takes a reference" ,
92- ref_pat,
93- pat,
94- itertools:: chain ( before, after) ,
95- ) ;
96- } ,
97- PatKind :: Tuple ( subpatterns, _) | PatKind :: TupleStruct ( _, subpatterns, _) => {
98- check_subpatterns (
99- cx,
100- "dereferencing a tuple pattern where every element takes a reference" ,
101- ref_pat,
102- pat,
103- subpatterns,
104- ) ;
105- } ,
106- PatKind :: Struct ( _, fields, _) => {
107- check_subpatterns (
108- cx,
109- "dereferencing a struct pattern where every field's pattern takes a reference" ,
110- ref_pat,
111- pat,
112- fields. iter ( ) . map ( |field| field. pat ) ,
113- ) ;
114- } ,
115- _ => { } ,
116- }
117109 }
118110}
119111
0 commit comments