Skip to content

Commit d8a281e

Browse files
committed
Added an unused_rounding lint
1 parent 3cc50a4 commit d8a281e

8 files changed

+112
-0
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -3821,6 +3821,7 @@ Released 2018-09-13
38213821
[`unused_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_collect
38223822
[`unused_io_amount`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_io_amount
38233823
[`unused_label`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_label
3824+
[`unused_rounding`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_rounding
38243825
[`unused_self`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_self
38253826
[`unused_unit`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_unit
38263827
[`unusual_byte_groupings`]: https://rust-lang.github.io/rust-clippy/master/index.html#unusual_byte_groupings

clippy_lints/src/lib.register_lints.rs

+1
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,7 @@ store.register_lints(&[
546546
unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME,
547547
unused_async::UNUSED_ASYNC,
548548
unused_io_amount::UNUSED_IO_AMOUNT,
549+
unused_rounding::UNUSED_ROUNDING,
549550
unused_self::UNUSED_SELF,
550551
unused_unit::UNUSED_UNIT,
551552
unwrap::PANICKING_UNWRAP,

clippy_lints/src/lib.register_nursery.rs

+1
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,6 @@ store.register_group(true, "clippy::nursery", Some("clippy_nursery"), vec![
3232
LintId::of(trait_bounds::TYPE_REPETITION_IN_BOUNDS),
3333
LintId::of(transmute::TRANSMUTE_UNDEFINED_REPR),
3434
LintId::of(transmute::USELESS_TRANSMUTE),
35+
LintId::of(unused_rounding::UNUSED_ROUNDING),
3536
LintId::of(use_self::USE_SELF),
3637
])

clippy_lints/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,7 @@ mod unnested_or_patterns;
402402
mod unsafe_removed_from_name;
403403
mod unused_async;
404404
mod unused_io_amount;
405+
mod unused_rounding;
405406
mod unused_self;
406407
mod unused_unit;
407408
mod unwrap;
@@ -906,6 +907,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
906907
store.register_late_pass(|| Box::new(rc_clone_in_vec_init::RcCloneInVecInit));
907908
store.register_early_pass(|| Box::new(duplicate_mod::DuplicateMod::default()));
908909
store.register_late_pass(|| Box::new(get_first::GetFirst));
910+
store.register_early_pass(|| Box::new(unused_rounding::UnusedRounding));
909911
// add lints here, do not remove this comment, it's used in `new_lint`
910912
}
911913

clippy_lints/src/unused_rounding.rs

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
use clippy_utils::diagnostics::span_lint_and_sugg;
2+
use rustc_ast::ast::{Expr, ExprKind, LitFloatType, LitKind};
3+
use rustc_errors::Applicability;
4+
use rustc_lint::{EarlyContext, EarlyLintPass};
5+
use rustc_session::{declare_lint_pass, declare_tool_lint};
6+
7+
declare_clippy_lint! {
8+
/// ### What it does
9+
///
10+
/// Detects cases where a whole-number literal float is being rounded, using
11+
/// the `floor`, `ceil`, or `round` methods.
12+
///
13+
/// ### Why is this bad?
14+
///
15+
/// This is unnecessary and confusing to the reader. Doing this is probably a mistake.
16+
///
17+
/// ### Example
18+
/// ```rust
19+
/// let x = 1f32.ceil();
20+
/// ```
21+
/// Use instead:
22+
/// ```rust
23+
/// let x = 1f32;
24+
/// ```
25+
#[clippy::version = "1.62.0"]
26+
pub UNUSED_ROUNDING,
27+
nursery,
28+
"Rounding a whole number literal, which is useless"
29+
}
30+
declare_lint_pass!(UnusedRounding => [UNUSED_ROUNDING]);
31+
32+
fn is_useless_rounding(expr: &Expr) -> Option<(&str, String)> {
33+
if let ExprKind::MethodCall(name_ident, args, _) = &expr.kind
34+
&& let method_name = name_ident.ident.name.as_str()
35+
&& (method_name == "ceil" || method_name == "round" || method_name == "floor")
36+
&& !args.is_empty()
37+
&& let ExprKind::Lit(spanned) = &args[0].kind
38+
&& let LitKind::Float(symbol, ty) = spanned.kind {
39+
let f = symbol.as_str().parse::<f64>().unwrap();
40+
let f_str = symbol.to_string() + if let LitFloatType::Suffixed(ty) = ty {
41+
ty.name_str()
42+
} else {
43+
""
44+
};
45+
if f.fract() < f64::EPSILON {
46+
Some((method_name, f_str))
47+
} else {
48+
None
49+
}
50+
} else {
51+
None
52+
}
53+
}
54+
55+
impl EarlyLintPass for UnusedRounding {
56+
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
57+
if let Some((method_name, float)) = is_useless_rounding(expr) {
58+
span_lint_and_sugg(
59+
cx,
60+
UNUSED_ROUNDING,
61+
expr.span,
62+
&format!("used the `{}` method with a whole number float", method_name),
63+
&format!("remove the `{}` method call", method_name),
64+
float,
65+
Applicability::MachineApplicable,
66+
);
67+
}
68+
}
69+
}

tests/ui/unused_rounding.fixed

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// run-rustfix
2+
#![warn(clippy::unused_rounding)]
3+
4+
fn main() {
5+
let _ = 1f32;
6+
let _ = 1.0f64;
7+
let _ = 1.00f32;
8+
}

tests/ui/unused_rounding.rs

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// run-rustfix
2+
#![warn(clippy::unused_rounding)]
3+
4+
fn main() {
5+
let _ = 1f32.ceil();
6+
let _ = 1.0f64.floor();
7+
let _ = 1.00f32.round();
8+
}

tests/ui/unused_rounding.stderr

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error: used the `ceil` method with a whole number float
2+
--> $DIR/unused_rounding.rs:5:13
3+
|
4+
LL | let _ = 1f32.ceil();
5+
| ^^^^^^^^^^^ help: remove the `ceil` method call: `1f32`
6+
|
7+
= note: `-D clippy::unused-rounding` implied by `-D warnings`
8+
9+
error: used the `floor` method with a whole number float
10+
--> $DIR/unused_rounding.rs:6:13
11+
|
12+
LL | let _ = 1.0f64.floor();
13+
| ^^^^^^^^^^^^^^ help: remove the `floor` method call: `1.0f64`
14+
15+
error: used the `round` method with a whole number float
16+
--> $DIR/unused_rounding.rs:7:13
17+
|
18+
LL | let _ = 1.00f32.round();
19+
| ^^^^^^^^^^^^^^^ help: remove the `round` method call: `1.00f32`
20+
21+
error: aborting due to 3 previous errors
22+

0 commit comments

Comments
 (0)