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+ } ;
24use crate :: utils:: { higher, sugg} ;
35use if_chain:: if_chain;
46use rustc:: hir;
@@ -68,52 +70,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps {
6870 match & expr. node {
6971 hir:: ExprKind :: AssignOp ( op, lhs, rhs) => {
7072 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) ;
11783 }
11884 }
11985 } ,
@@ -140,13 +106,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps {
140106 } ;
141107 // check that we are not inside an `impl AssignOp` of this exact operation
142108 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
145109 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) ;
150111 if trait_ref. path. def. def_id( ) == trait_id;
151112 then { return ; }
152113 }
@@ -234,6 +195,48 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps {
234195 }
235196}
236197
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+
237240fn is_commutative ( op : hir:: BinOpKind ) -> bool {
238241 use rustc:: hir:: BinOpKind :: * ;
239242 match op {
0 commit comments