Skip to content

Commit 85670af

Browse files
Add lint to detect conversions between degrees and radians
1 parent e022819 commit 85670af

File tree

5 files changed

+119
-9
lines changed

5 files changed

+119
-9
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

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

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

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

clippy_lints/src/floating_point_arithmetic.rs

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -126,17 +126,17 @@ fn check_ln1p(cx: &LateContext<'_, '_>, expr: &Expr, args: &HirVec<Expr>) {
126126
// casted without loss
127127
#[allow(clippy::cast_possible_truncation)]
128128
fn get_integer_from_float_constant(value: &Constant) -> Option<i64> {
129-
match value {
130-
F32(num) if (num.trunc() - num).abs() <= std::f32::EPSILON => {
131-
if *num > -16_777_217.0 && *num < 16_777_217.0 {
132-
Some(num.round() as i64)
129+
match *value {
130+
F32(num) if num.trunc() - num == 0.0 => {
131+
if num > -16_777_217.0 && num < 16_777_217.0 {
132+
Some(num as i64)
133133
} else {
134134
None
135135
}
136136
},
137-
F64(num) if (num.trunc() - num).abs() <= std::f64::EPSILON => {
138-
if *num > -9_007_199_254_740_993.0 && *num < 9_007_199_254_740_993.0 {
139-
Some(num.round() as i64)
137+
F64(num) if num.trunc() - num == 0.0 => {
138+
if num > -9_007_199_254_740_993.0 && num < 9_007_199_254_740_993.0 {
139+
Some(num as i64)
140140
} else {
141141
None
142142
}
@@ -313,6 +313,41 @@ fn check_log_division(cx: &LateContext<'_, '_>, expr: &Expr) {
313313
}
314314
}
315315

316+
fn check_conversion_between_deg_and_rad(cx: &LateContext<'_, '_>, expr: &'_ Expr) {
317+
if_chain! {
318+
if let ExprKind::Binary(op, ref lhs, ref rhs) = expr.kind;
319+
if op.node == BinOpKind::Mul;
320+
if cx.tables.expr_ty(lhs).is_floating_point();
321+
then {
322+
let (recv, value) = if let Some((value, _)) = constant(cx, cx.tables, lhs) {
323+
(rhs, value)
324+
} else if let Some((value, _)) = constant(cx, cx.tables, rhs) {
325+
(lhs, value)
326+
} else {
327+
return;
328+
};
329+
330+
let unit = if F32(f32_consts::PI / 180.0) == value || F64(f64_consts::PI / 180.0) == value {
331+
"radians"
332+
} else if F32(180.0 / f32_consts::PI) == value || F64(180.0 / f64_consts::PI) == value {
333+
"degrees"
334+
} else {
335+
return;
336+
};
337+
338+
span_lint_and_sugg(
339+
cx,
340+
FLOATING_POINT_IMPROVEMENTS,
341+
expr.span,
342+
"conversions between degrees and radians can be expressed more succinctly",
343+
"consider using",
344+
format!("{}.to_{}()", sugg::Sugg::hir(cx, recv, "..").maybe_par(), unit),
345+
Applicability::MachineApplicable,
346+
);
347+
}
348+
}
349+
}
350+
316351
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FloatingPointArithmetic {
317352
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
318353
if let ExprKind::MethodCall(ref path, _, args) = &expr.kind {
@@ -329,6 +364,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FloatingPointArithmetic {
329364
} else {
330365
check_expm1(cx, expr);
331366
check_log_division(cx, expr);
367+
check_conversion_between_deg_and_rad(cx, expr);
332368
}
333369
}
334370
}

src/lintlist/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ pub use lint::Lint;
66
pub use lint::LINT_LEVELS;
77

88
// begin lint list, do not remove this comment, it’s used in `update_lints`
9-
pub const ALL_LINTS: [Lint; 340] = [
9+
pub const ALL_LINTS: [Lint; 341] = [
1010
Lint {
1111
name: "absurd_extreme_comparisons",
1212
group: "correctness",
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#![warn(clippy::floating_point_improvements)]
2+
3+
fn main() {
4+
let x = 2f32;
5+
let _ = x * (std::f32::consts::PI / 180.0);
6+
let _ = (std::f32::consts::PI / 180.0) * x;
7+
let _ = -x * (std::f32::consts::PI / 180.0);
8+
let _ = x * (180.0 / std::f32::consts::PI);
9+
let _ = (180.0 / std::f32::consts::PI) * x;
10+
11+
let x = 2f64;
12+
let _ = x * (std::f64::consts::PI / 180.0);
13+
let _ = (std::f64::consts::PI / 180.0) * x;
14+
let _ = x * (180.0 / std::f64::consts::PI);
15+
let _ = (180.0 / std::f64::consts::PI) * x;
16+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
error: conversions between degrees and radians can be expressed more succinctly
2+
--> $DIR/floating_point_deg_rad_conversion.rs:5:13
3+
|
4+
LL | let _ = x * (std::f32::consts::PI / 180.0);
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.to_radians()`
6+
|
7+
= note: `-D clippy::floating-point-improvements` implied by `-D warnings`
8+
9+
error: conversions between degrees and radians can be expressed more succinctly
10+
--> $DIR/floating_point_deg_rad_conversion.rs:6:13
11+
|
12+
LL | let _ = (std::f32::consts::PI / 180.0) * x;
13+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.to_radians()`
14+
15+
error: conversions between degrees and radians can be expressed more succinctly
16+
--> $DIR/floating_point_deg_rad_conversion.rs:7:13
17+
|
18+
LL | let _ = -x * (std::f32::consts::PI / 180.0);
19+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(-x).to_radians()`
20+
21+
error: conversions between degrees and radians can be expressed more succinctly
22+
--> $DIR/floating_point_deg_rad_conversion.rs:8:13
23+
|
24+
LL | let _ = x * (180.0 / std::f32::consts::PI);
25+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.to_degrees()`
26+
27+
error: conversions between degrees and radians can be expressed more succinctly
28+
--> $DIR/floating_point_deg_rad_conversion.rs:9:13
29+
|
30+
LL | let _ = (180.0 / std::f32::consts::PI) * x;
31+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.to_degrees()`
32+
33+
error: conversions between degrees and radians can be expressed more succinctly
34+
--> $DIR/floating_point_deg_rad_conversion.rs:12:13
35+
|
36+
LL | let _ = x * (std::f64::consts::PI / 180.0);
37+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.to_radians()`
38+
39+
error: conversions between degrees and radians can be expressed more succinctly
40+
--> $DIR/floating_point_deg_rad_conversion.rs:13:13
41+
|
42+
LL | let _ = (std::f64::consts::PI / 180.0) * x;
43+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.to_radians()`
44+
45+
error: conversions between degrees and radians can be expressed more succinctly
46+
--> $DIR/floating_point_deg_rad_conversion.rs:14:13
47+
|
48+
LL | let _ = x * (180.0 / std::f64::consts::PI);
49+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.to_degrees()`
50+
51+
error: conversions between degrees and radians can be expressed more succinctly
52+
--> $DIR/floating_point_deg_rad_conversion.rs:15:13
53+
|
54+
LL | let _ = (180.0 / std::f64::consts::PI) * x;
55+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.to_degrees()`
56+
57+
error: aborting due to 9 previous errors
58+

0 commit comments

Comments
 (0)