|
1 | 1 | use clippy_utils::diagnostics::span_lint_and_then; |
2 | 2 | use clippy_utils::source::snippet_opt; |
3 | 3 | use clippy_utils::ty::implements_trait; |
4 | | -use clippy_utils::{eq_expr_value, get_trait_def_id, trait_ref_of_method}; |
5 | | -use clippy_utils::{higher, paths, sugg}; |
| 4 | +use clippy_utils::{binop_traits, sugg}; |
| 5 | +use clippy_utils::{eq_expr_value, trait_ref_of_method}; |
6 | 6 | use if_chain::if_chain; |
7 | 7 | use rustc_errors::Applicability; |
8 | 8 | use rustc_hir as hir; |
@@ -85,71 +85,34 @@ impl<'tcx> LateLintPass<'tcx> for AssignOps { |
85 | 85 | let lint = |assignee: &hir::Expr<'_>, rhs: &hir::Expr<'_>| { |
86 | 86 | let ty = cx.typeck_results().expr_ty(assignee); |
87 | 87 | let rty = cx.typeck_results().expr_ty(rhs); |
88 | | - macro_rules! ops { |
89 | | - ($op:expr, |
90 | | - $cx:expr, |
91 | | - $ty:expr, |
92 | | - $rty:expr, |
93 | | - $($trait_name:ident),+) => { |
94 | | - match $op { |
95 | | - $(hir::BinOpKind::$trait_name => { |
96 | | - let [krate, module] = paths::OPS_MODULE; |
97 | | - let path: [&str; 3] = [krate, module, concat!(stringify!($trait_name), "Assign")]; |
98 | | - let trait_id = if let Some(trait_id) = get_trait_def_id($cx, &path) { |
99 | | - trait_id |
100 | | - } else { |
101 | | - return; // useless if the trait doesn't exist |
102 | | - }; |
103 | | - // check that we are not inside an `impl AssignOp` of this exact operation |
104 | | - let parent_fn = cx.tcx.hir().get_parent_item(e.hir_id); |
105 | | - if_chain! { |
106 | | - if let Some(trait_ref) = trait_ref_of_method(cx, parent_fn); |
107 | | - if trait_ref.path.res.def_id() == trait_id; |
108 | | - then { return; } |
| 88 | + if_chain! { |
| 89 | + if let Some((_, lang_item)) = binop_traits(op.node); |
| 90 | + if let Ok(trait_id) = cx.tcx.lang_items().require(lang_item); |
| 91 | + let parent_fn = cx.tcx.hir().get_parent_item(e.hir_id); |
| 92 | + if trait_ref_of_method(cx, parent_fn) |
| 93 | + .map_or(true, |t| t.path.res.def_id() != trait_id); |
| 94 | + if implements_trait(cx, ty, trait_id, &[rty.into()]); |
| 95 | + then { |
| 96 | + span_lint_and_then( |
| 97 | + cx, |
| 98 | + ASSIGN_OP_PATTERN, |
| 99 | + expr.span, |
| 100 | + "manual implementation of an assign operation", |
| 101 | + |diag| { |
| 102 | + if let (Some(snip_a), Some(snip_r)) = |
| 103 | + (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span)) |
| 104 | + { |
| 105 | + diag.span_suggestion( |
| 106 | + expr.span, |
| 107 | + "replace it with", |
| 108 | + format!("{} {}= {}", snip_a, op.node.as_str(), snip_r), |
| 109 | + Applicability::MachineApplicable, |
| 110 | + ); |
109 | 111 | } |
110 | | - implements_trait($cx, $ty, trait_id, &[$rty]) |
111 | | - },)* |
112 | | - _ => false, |
113 | | - } |
| 112 | + }, |
| 113 | + ); |
114 | 114 | } |
115 | 115 | } |
116 | | - if ops!( |
117 | | - op.node, |
118 | | - cx, |
119 | | - ty, |
120 | | - rty.into(), |
121 | | - Add, |
122 | | - Sub, |
123 | | - Mul, |
124 | | - Div, |
125 | | - Rem, |
126 | | - And, |
127 | | - Or, |
128 | | - BitAnd, |
129 | | - BitOr, |
130 | | - BitXor, |
131 | | - Shr, |
132 | | - Shl |
133 | | - ) { |
134 | | - span_lint_and_then( |
135 | | - cx, |
136 | | - ASSIGN_OP_PATTERN, |
137 | | - expr.span, |
138 | | - "manual implementation of an assign operation", |
139 | | - |diag| { |
140 | | - if let (Some(snip_a), Some(snip_r)) = |
141 | | - (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span)) |
142 | | - { |
143 | | - diag.span_suggestion( |
144 | | - expr.span, |
145 | | - "replace it with", |
146 | | - format!("{} {}= {}", snip_a, op.node.as_str(), snip_r), |
147 | | - Applicability::MachineApplicable, |
148 | | - ); |
149 | | - } |
150 | | - }, |
151 | | - ); |
152 | | - } |
153 | 116 | }; |
154 | 117 |
|
155 | 118 | let mut visitor = ExprVisitor { |
@@ -206,7 +169,7 @@ fn lint_misrefactored_assign_op( |
206 | 169 | if let (Some(snip_a), Some(snip_r)) = (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs_other.span)) { |
207 | 170 | let a = &sugg::Sugg::hir(cx, assignee, ".."); |
208 | 171 | let r = &sugg::Sugg::hir(cx, rhs, ".."); |
209 | | - let long = format!("{} = {}", snip_a, sugg::make_binop(higher::binop(op.node), a, r)); |
| 172 | + let long = format!("{} = {}", snip_a, sugg::make_binop(op.node.into(), a, r)); |
210 | 173 | diag.span_suggestion( |
211 | 174 | expr.span, |
212 | 175 | &format!( |
|
0 commit comments