Skip to content

Commit f8349e1

Browse files
authored
Merge pull request #1318 from oli-obk/op_assign_false_positive
don't lint on x = x + y inside an AddAssign impl
2 parents ea0227f + 5f6cae0 commit f8349e1

File tree

3 files changed

+36
-1
lines changed

3 files changed

+36
-1
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ clippy_lints = { version = "0.0.104", path = "clippy_lints" }
2929
# end automatic update
3030

3131
[dev-dependencies]
32-
compiletest_rs = "0.2.1"
32+
compiletest_rs = "0.2.5"
3333
lazy_static = "0.1.15"
3434
regex = "0.1.71"
3535
rustc-serialize = "0.3"

clippy_lints/src/assign_ops.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use rustc::hir;
22
use rustc::lint::*;
3+
use syntax::ast;
34
use utils::{span_lint_and_then, snippet_opt, SpanlessEq, get_trait_def_id, implements_trait};
45
use utils::{higher, sugg};
56

@@ -135,6 +136,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps {
135136
} else {
136137
return; // useless if the trait doesn't exist
137138
};
139+
// check that we are not inside an `impl AssignOp` of this exact operation
140+
let parent_fn = cx.tcx.map.get_parent(e.id);
141+
let parent_impl = cx.tcx.map.get_parent(parent_fn);
142+
// the crate node is the only one that is not in the map
143+
if parent_impl != ast::CRATE_NODE_ID {
144+
if let hir::map::Node::NodeItem(item) = cx.tcx.map.get(parent_impl) {
145+
if let hir::Item_::ItemImpl(_, _, _, Some(ref trait_ref), _, _) = item.node {
146+
if trait_ref.path.def.def_id() == trait_id {
147+
return;
148+
}
149+
}
150+
}
151+
}
138152
implements_trait($cx, $ty, trait_id, vec![$rty])
139153
},)*
140154
_ => false,

tests/compile-fail/assign_ops2.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,24 @@ fn main() {
3434
a %= 42 % a;
3535
a <<= 6 << a;
3636
}
37+
38+
// check that we don't lint on op assign impls, because that's just the way to impl them
39+
40+
use std::ops::{Mul, MulAssign};
41+
42+
#[derive(Copy, Clone, Debug, PartialEq)]
43+
pub struct Wrap(i64);
44+
45+
impl Mul<i64> for Wrap {
46+
type Output = Self;
47+
48+
fn mul(self, rhs: i64) -> Self {
49+
Wrap(self.0 * rhs)
50+
}
51+
}
52+
53+
impl MulAssign<i64> for Wrap {
54+
fn mul_assign(&mut self, rhs: i64) {
55+
*self = *self * rhs
56+
}
57+
}

0 commit comments

Comments
 (0)