1 use clippy_utils::diagnostics::span_lint_and_sugg;
2 use rustc_ast::ast::{Expr, ExprKind, MethodCall};
3 use rustc_errors::Applicability;
4 use rustc_lint::{EarlyContext, EarlyLintPass};
5 use rustc_session::{declare_lint_pass, declare_tool_lint};
10 /// Detects cases where a whole-number literal float is being rounded, using
11 /// the `floor`, `ceil`, or `round` methods.
13 /// ### Why is this bad?
15 /// This is unnecessary and confusing to the reader. Doing this is probably a mistake.
19 /// let x = 1f32.ceil();
25 #[clippy::version = "1.63.0"]
28 "Uselessly rounding a whole number floating-point literal"
30 declare_lint_pass!(UnusedRounding => [UNUSED_ROUNDING]);
32 fn is_useless_rounding(expr: &Expr) -> Option<(&str, String)> {
33 if let ExprKind::MethodCall(box MethodCall { seg, receiver, .. }) = &expr.kind
34 && let method_name = seg.ident.name.as_str()
35 && (method_name == "ceil" || method_name == "round" || method_name == "floor")
36 && let ExprKind::Lit(token_lit) = &receiver.kind
37 && token_lit.is_semantic_float() {
38 let f = token_lit.symbol.as_str().parse::<f64>().unwrap();
39 let mut f_str = token_lit.symbol.to_string();
40 match token_lit.suffix {
41 Some(suffix) => f_str.push_str(suffix.as_str()),
45 Some((method_name, f_str))
54 impl EarlyLintPass for UnusedRounding {
55 fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
56 if let Some((method_name, float)) = is_useless_rounding(expr) {
61 &format!("used the `{method_name}` method with a whole number float"),
62 &format!("remove the `{method_name}` method call"),
64 Applicability::MachineApplicable,