Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
3331: Disable arithmetic lints in constant items r=oli-obk a=pengowen123

Currently this will not catch cases in associated constants. I'm not sure whether checking spans is the best way to solve this issue, but I don't think it will cause any problems.
Fixes rust-lang#1858

Co-authored-by: Owen Sanchez <pengowen816@gmail.com>
  • Loading branch information
bors[bot] and pengowen123 committed Oct 25, 2018
2 parents 757750d + 0b9e9c9 commit a87e1b0
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 8 deletions.
55 changes: 47 additions & 8 deletions clippy_lints/src/arithmetic.rs
Expand Up @@ -51,7 +51,9 @@ declare_clippy_lint! {

#[derive(Copy, Clone, Default)]
pub struct Arithmetic {
span: Option<Span>,
expr_span: Option<Span>,
/// This field is used to check whether expressions are constants, such as in enum discriminants and consts
const_span: Option<Span>,
}

impl LintPass for Arithmetic {
Expand All @@ -62,9 +64,15 @@ impl LintPass for Arithmetic {

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Arithmetic {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) {
if self.span.is_some() {
if self.expr_span.is_some() {
return;
}

if let Some(span) = self.const_span {
if span.contains(expr.span) {
return;
}
}
match expr.node {
hir::ExprKind::Binary(ref op, ref l, ref r) => {
match op.node {
Expand All @@ -86,29 +94,60 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Arithmetic {
let (l_ty, r_ty) = (cx.tables.expr_ty(l), cx.tables.expr_ty(r));
if l_ty.is_integral() && r_ty.is_integral() {
span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
self.span = Some(expr.span);
self.expr_span = Some(expr.span);
} else if l_ty.is_floating_point() && r_ty.is_floating_point() {
span_lint(cx, FLOAT_ARITHMETIC, expr.span, "floating-point arithmetic detected");
self.span = Some(expr.span);
self.expr_span = Some(expr.span);
}
},
hir::ExprKind::Unary(hir::UnOp::UnNeg, ref arg) => {
let ty = cx.tables.expr_ty(arg);
if ty.is_integral() {
span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
self.span = Some(expr.span);
self.expr_span = Some(expr.span);
} else if ty.is_floating_point() {
span_lint(cx, FLOAT_ARITHMETIC, expr.span, "floating-point arithmetic detected");
self.span = Some(expr.span);
self.expr_span = Some(expr.span);
}
},
_ => (),
}
}

fn check_expr_post(&mut self, _: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) {
if Some(expr.span) == self.span {
self.span = None;
if Some(expr.span) == self.expr_span {
self.expr_span = None;
}
}

fn check_body(&mut self, cx: &LateContext<'_, '_>, body: &hir::Body) {
let body_owner = cx.tcx.hir.body_owner(body.id());

match cx.tcx.hir.body_owner_kind(body_owner) {
hir::BodyOwnerKind::Static(_)
| hir::BodyOwnerKind::Const => {
let body_span = cx.tcx.hir.span(body_owner);

if let Some(span) = self.const_span {
if span.contains(body_span) {
return;
}
}
self.const_span = Some(body_span);
}
hir::BodyOwnerKind::Fn => (),
}
}

fn check_body_post(&mut self, cx: &LateContext<'_, '_>, body: &hir::Body) {
let body_owner = cx.tcx.hir.body_owner(body.id());
let body_span = cx.tcx.hir.span(body_owner);

if let Some(span) = self.const_span {
if span.contains(body_span) {
return;
}
}
self.const_span = None;
}
}
32 changes: 32 additions & 0 deletions tests/ui/arithmetic.rs
Expand Up @@ -37,4 +37,36 @@ fn main() {
f / 2.0;
f - 2.0 * 4.2;
-f;

// No errors for the following items because they are constant expressions
enum Foo {
Bar = -2,
}
struct Baz([i32; 1 + 1]);
union Qux {
field: [i32; 1 + 1],
}
type Alias = [i32; 1 + 1];

const FOO: i32 = -2;
static BAR: i32 = -2;

let _: [i32; 1 + 1] = [0, 0];

let _: [i32; 1 + 1] = {
let a: [i32; 1 + 1] = [0, 0];
a
};

trait Trait {
const ASSOC: i32 = 1 + 1;
}

impl Trait for Foo {
const ASSOC: i32 = {
let _: [i32; 1 + 1];
fn foo() {}
1 + 1
};
}
}

0 comments on commit a87e1b0

Please sign in to comment.