|
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