Skip to content

Commit

Permalink
Add lint to detect conversions between degrees and radians
Browse files Browse the repository at this point in the history
  • Loading branch information
krishna-veerareddy committed Dec 23, 2019
1 parent e022819 commit 85670af
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 9 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code.

[There are 340 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
[There are 341 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)

We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you:

Expand Down
50 changes: 43 additions & 7 deletions clippy_lints/src/floating_point_arithmetic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,17 +126,17 @@ fn check_ln1p(cx: &LateContext<'_, '_>, expr: &Expr, args: &HirVec<Expr>) {
// casted without loss
#[allow(clippy::cast_possible_truncation)]
fn get_integer_from_float_constant(value: &Constant) -> Option<i64> {
match value {
F32(num) if (num.trunc() - num).abs() <= std::f32::EPSILON => {
if *num > -16_777_217.0 && *num < 16_777_217.0 {
Some(num.round() as i64)
match *value {
F32(num) if num.trunc() - num == 0.0 => {
if num > -16_777_217.0 && num < 16_777_217.0 {
Some(num as i64)
} else {
None
}
},
F64(num) if (num.trunc() - num).abs() <= std::f64::EPSILON => {
if *num > -9_007_199_254_740_993.0 && *num < 9_007_199_254_740_993.0 {
Some(num.round() as i64)
F64(num) if num.trunc() - num == 0.0 => {
if num > -9_007_199_254_740_993.0 && num < 9_007_199_254_740_993.0 {
Some(num as i64)
} else {
None
}
Expand Down Expand Up @@ -313,6 +313,41 @@ fn check_log_division(cx: &LateContext<'_, '_>, expr: &Expr) {
}
}

fn check_conversion_between_deg_and_rad(cx: &LateContext<'_, '_>, expr: &'_ Expr) {
if_chain! {
if let ExprKind::Binary(op, ref lhs, ref rhs) = expr.kind;
if op.node == BinOpKind::Mul;
if cx.tables.expr_ty(lhs).is_floating_point();
then {
let (recv, value) = if let Some((value, _)) = constant(cx, cx.tables, lhs) {
(rhs, value)
} else if let Some((value, _)) = constant(cx, cx.tables, rhs) {
(lhs, value)
} else {
return;
};

let unit = if F32(f32_consts::PI / 180.0) == value || F64(f64_consts::PI / 180.0) == value {
"radians"
} else if F32(180.0 / f32_consts::PI) == value || F64(180.0 / f64_consts::PI) == value {
"degrees"
} else {
return;
};

span_lint_and_sugg(
cx,
FLOATING_POINT_IMPROVEMENTS,
expr.span,
"conversions between degrees and radians can be expressed more succinctly",
"consider using",
format!("{}.to_{}()", sugg::Sugg::hir(cx, recv, "..").maybe_par(), unit),
Applicability::MachineApplicable,
);
}
}
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FloatingPointArithmetic {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if let ExprKind::MethodCall(ref path, _, args) = &expr.kind {
Expand All @@ -329,6 +364,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FloatingPointArithmetic {
} else {
check_expm1(cx, expr);
check_log_division(cx, expr);
check_conversion_between_deg_and_rad(cx, expr);
}
}
}
2 changes: 1 addition & 1 deletion src/lintlist/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ pub use lint::Lint;
pub use lint::LINT_LEVELS;

// begin lint list, do not remove this comment, it’s used in `update_lints`
pub const ALL_LINTS: [Lint; 340] = [
pub const ALL_LINTS: [Lint; 341] = [
Lint {
name: "absurd_extreme_comparisons",
group: "correctness",
Expand Down
16 changes: 16 additions & 0 deletions tests/ui/floating_point_deg_rad_conversion.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#![warn(clippy::floating_point_improvements)]

fn main() {
let x = 2f32;
let _ = x * (std::f32::consts::PI / 180.0);
let _ = (std::f32::consts::PI / 180.0) * x;
let _ = -x * (std::f32::consts::PI / 180.0);
let _ = x * (180.0 / std::f32::consts::PI);
let _ = (180.0 / std::f32::consts::PI) * x;

let x = 2f64;
let _ = x * (std::f64::consts::PI / 180.0);
let _ = (std::f64::consts::PI / 180.0) * x;
let _ = x * (180.0 / std::f64::consts::PI);
let _ = (180.0 / std::f64::consts::PI) * x;
}
58 changes: 58 additions & 0 deletions tests/ui/floating_point_deg_rad_conversion.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
error: conversions between degrees and radians can be expressed more succinctly
--> $DIR/floating_point_deg_rad_conversion.rs:5:13
|
LL | let _ = x * (std::f32::consts::PI / 180.0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.to_radians()`
|
= note: `-D clippy::floating-point-improvements` implied by `-D warnings`

error: conversions between degrees and radians can be expressed more succinctly
--> $DIR/floating_point_deg_rad_conversion.rs:6:13
|
LL | let _ = (std::f32::consts::PI / 180.0) * x;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.to_radians()`

error: conversions between degrees and radians can be expressed more succinctly
--> $DIR/floating_point_deg_rad_conversion.rs:7:13
|
LL | let _ = -x * (std::f32::consts::PI / 180.0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(-x).to_radians()`

error: conversions between degrees and radians can be expressed more succinctly
--> $DIR/floating_point_deg_rad_conversion.rs:8:13
|
LL | let _ = x * (180.0 / std::f32::consts::PI);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.to_degrees()`

error: conversions between degrees and radians can be expressed more succinctly
--> $DIR/floating_point_deg_rad_conversion.rs:9:13
|
LL | let _ = (180.0 / std::f32::consts::PI) * x;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.to_degrees()`

error: conversions between degrees and radians can be expressed more succinctly
--> $DIR/floating_point_deg_rad_conversion.rs:12:13
|
LL | let _ = x * (std::f64::consts::PI / 180.0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.to_radians()`

error: conversions between degrees and radians can be expressed more succinctly
--> $DIR/floating_point_deg_rad_conversion.rs:13:13
|
LL | let _ = (std::f64::consts::PI / 180.0) * x;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.to_radians()`

error: conversions between degrees and radians can be expressed more succinctly
--> $DIR/floating_point_deg_rad_conversion.rs:14:13
|
LL | let _ = x * (180.0 / std::f64::consts::PI);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.to_degrees()`

error: conversions between degrees and radians can be expressed more succinctly
--> $DIR/floating_point_deg_rad_conversion.rs:15:13
|
LL | let _ = (180.0 / std::f64::consts::PI) * x;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.to_degrees()`

error: aborting due to 9 previous errors

0 comments on commit 85670af

Please sign in to comment.