1
- use crate :: utils:: { get_trait_def_id, implements_trait, snippet_opt, span_lint_and_then, SpanlessEq } ;
1
+ use crate :: utils:: {
2
+ get_trait_def_id, implements_trait, snippet_opt, span_lint_and_then, trait_ref_of_method, SpanlessEq ,
3
+ } ;
2
4
use crate :: utils:: { higher, sugg} ;
3
5
use if_chain:: if_chain;
4
6
use rustc:: hir;
@@ -68,52 +70,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps {
68
70
match & expr. node {
69
71
hir:: ExprKind :: AssignOp ( op, lhs, rhs) => {
70
72
if let hir:: ExprKind :: Binary ( binop, l, r) = & rhs. node {
71
- if op. node == binop. node {
72
- let lint = |assignee : & hir:: Expr , rhs_other : & hir:: Expr | {
73
- span_lint_and_then (
74
- cx,
75
- MISREFACTORED_ASSIGN_OP ,
76
- expr. span ,
77
- "variable appears on both sides of an assignment operation" ,
78
- |db| {
79
- if let ( Some ( snip_a) , Some ( snip_r) ) =
80
- ( snippet_opt ( cx, assignee. span ) , snippet_opt ( cx, rhs_other. span ) )
81
- {
82
- let a = & sugg:: Sugg :: hir ( cx, assignee, ".." ) ;
83
- let r = & sugg:: Sugg :: hir ( cx, rhs, ".." ) ;
84
- let long =
85
- format ! ( "{} = {}" , snip_a, sugg:: make_binop( higher:: binop( op. node) , a, r) ) ;
86
- db. span_suggestion (
87
- expr. span ,
88
- & format ! (
89
- "Did you mean {} = {} {} {} or {}? Consider replacing it with" ,
90
- snip_a,
91
- snip_a,
92
- op. node. as_str( ) ,
93
- snip_r,
94
- long
95
- ) ,
96
- format ! ( "{} {}= {}" , snip_a, op. node. as_str( ) , snip_r) ,
97
- Applicability :: MachineApplicable ,
98
- ) ;
99
- db. span_suggestion (
100
- expr. span ,
101
- "or" ,
102
- long,
103
- Applicability :: MachineApplicable , // snippet
104
- ) ;
105
- }
106
- } ,
107
- ) ;
108
- } ;
109
- // lhs op= l op r
110
- if SpanlessEq :: new ( cx) . ignore_fn ( ) . eq_expr ( lhs, l) {
111
- lint ( lhs, r) ;
112
- }
113
- // lhs op= l commutative_op r
114
- if is_commutative ( op. node ) && SpanlessEq :: new ( cx) . ignore_fn ( ) . eq_expr ( lhs, r) {
115
- lint ( lhs, l) ;
116
- }
73
+ if op. node != binop. node {
74
+ return ;
75
+ }
76
+ // lhs op= l op r
77
+ if SpanlessEq :: new ( cx) . ignore_fn ( ) . eq_expr ( lhs, l) {
78
+ lint_misrefactored_assign_op ( cx, expr, * op, rhs, lhs, r) ;
79
+ }
80
+ // lhs op= l commutative_op r
81
+ if is_commutative ( op. node ) && SpanlessEq :: new ( cx) . ignore_fn ( ) . eq_expr ( lhs, r) {
82
+ lint_misrefactored_assign_op ( cx, expr, * op, rhs, lhs, l) ;
117
83
}
118
84
}
119
85
} ,
@@ -140,13 +106,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps {
140
106
} ;
141
107
// check that we are not inside an `impl AssignOp` of this exact operation
142
108
let parent_fn = cx. tcx. hir( ) . get_parent_item( e. hir_id) ;
143
- let parent_impl = cx. tcx. hir( ) . get_parent_item( parent_fn) ;
144
- // the crate node is the only one that is not in the map
145
109
if_chain! {
146
- if parent_impl != hir:: CRATE_HIR_ID ;
147
- if let hir:: Node :: Item ( item) = cx. tcx. hir( ) . get_by_hir_id( parent_impl) ;
148
- if let hir:: ItemKind :: Impl ( _, _, _, _, Some ( trait_ref) , _, _) =
149
- & item. node;
110
+ if let Some ( trait_ref) = trait_ref_of_method( cx, parent_fn) ;
150
111
if trait_ref. path. def. def_id( ) == trait_id;
151
112
then { return ; }
152
113
}
@@ -234,6 +195,48 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps {
234
195
}
235
196
}
236
197
198
+ fn lint_misrefactored_assign_op (
199
+ cx : & LateContext < ' _ , ' _ > ,
200
+ expr : & hir:: Expr ,
201
+ op : hir:: BinOp ,
202
+ rhs : & hir:: Expr ,
203
+ assignee : & hir:: Expr ,
204
+ rhs_other : & hir:: Expr ,
205
+ ) {
206
+ span_lint_and_then (
207
+ cx,
208
+ MISREFACTORED_ASSIGN_OP ,
209
+ expr. span ,
210
+ "variable appears on both sides of an assignment operation" ,
211
+ |db| {
212
+ if let ( Some ( snip_a) , Some ( snip_r) ) = ( snippet_opt ( cx, assignee. span ) , snippet_opt ( cx, rhs_other. span ) ) {
213
+ let a = & sugg:: Sugg :: hir ( cx, assignee, ".." ) ;
214
+ let r = & sugg:: Sugg :: hir ( cx, rhs, ".." ) ;
215
+ let long = format ! ( "{} = {}" , snip_a, sugg:: make_binop( higher:: binop( op. node) , a, r) ) ;
216
+ db. span_suggestion (
217
+ expr. span ,
218
+ & format ! (
219
+ "Did you mean {} = {} {} {} or {}? Consider replacing it with" ,
220
+ snip_a,
221
+ snip_a,
222
+ op. node. as_str( ) ,
223
+ snip_r,
224
+ long
225
+ ) ,
226
+ format ! ( "{} {}= {}" , snip_a, op. node. as_str( ) , snip_r) ,
227
+ Applicability :: MachineApplicable ,
228
+ ) ;
229
+ db. span_suggestion (
230
+ expr. span ,
231
+ "or" ,
232
+ long,
233
+ Applicability :: MachineApplicable , // snippet
234
+ ) ;
235
+ }
236
+ } ,
237
+ ) ;
238
+ }
239
+
237
240
fn is_commutative ( op : hir:: BinOpKind ) -> bool {
238
241
use rustc:: hir:: BinOpKind :: * ;
239
242
match op {
0 commit comments