diff --git a/README.md b/README.md index 46fbc9dc9a46..be5433029de8 100644 --- a/README.md +++ b/README.md @@ -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: diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index e184b4a88f77..1ad9671fa3fd 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -126,17 +126,17 @@ fn check_ln1p(cx: &LateContext<'_, '_>, expr: &Expr, args: &HirVec) { // casted without loss #[allow(clippy::cast_possible_truncation)] fn get_integer_from_float_constant(value: &Constant) -> Option { - 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 } @@ -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 { @@ -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); } } } diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 869c22bf7da8..dea9da7b30a9 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -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", diff --git a/tests/ui/floating_point_deg_rad_conversion.rs b/tests/ui/floating_point_deg_rad_conversion.rs new file mode 100644 index 000000000000..42bdfe967427 --- /dev/null +++ b/tests/ui/floating_point_deg_rad_conversion.rs @@ -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; +} diff --git a/tests/ui/floating_point_deg_rad_conversion.stderr b/tests/ui/floating_point_deg_rad_conversion.stderr new file mode 100644 index 000000000000..1ad6968d685e --- /dev/null +++ b/tests/ui/floating_point_deg_rad_conversion.stderr @@ -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 +