diff --git a/clippy_lints/src/float_literal.rs b/clippy_lints/src/float_literal.rs index c51267567d01..56f0873c1455 100644 --- a/clippy_lints/src/float_literal.rs +++ b/clippy_lints/src/float_literal.rs @@ -13,6 +13,8 @@ declare_clippy_lint! { /// Checks for float literals with a precision greater /// than that supported by the underlying type. /// + /// The lint is suppressed for literals with over 40 digits. + /// /// ### Why is this bad? /// Rust will truncate the literal silently. /// @@ -126,13 +128,23 @@ impl<'tcx> LateLintPass<'tcx> for FloatLiteral { }, ); } - } else if digits > max as usize && count_digits(&float_str) < count_digits(sym_str) { + } else if digits > max as usize && count_digits(&float_str) < digits { + if digits >= 40 && is_const_item(cx, expr) { + // If a big enough number of digits is specified and it's a constant + // we assume the user is definining a constant, and excessive precision is ok + return; + } span_lint_and_then( cx, EXCESSIVE_PRECISION, expr.span, "float has excessive precision", |diag| { + if digits >= 40 + && let Some(let_stmt) = maybe_let_stmt(cx, expr) + { + diag.span_note(let_stmt.span, "consider making it a `const` item"); + } diag.span_suggestion_verbose( expr.span, "consider changing the type or truncating it to", @@ -196,3 +208,19 @@ impl FloatFormat { } } } + +fn is_const_item(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool { + let parent = cx.tcx.parent_hir_node(expr.hir_id); + if let hir::Node::Item(itm) = parent { + return matches!(itm.kind, hir::ItemKind::Const(..)); + } + false +} + +fn maybe_let_stmt<'a>(cx: &LateContext<'a>, expr: &hir::Expr<'_>) -> Option<&'a hir::LetStmt<'a>> { + let parent = cx.tcx.parent_hir_node(expr.hir_id); + match parent { + hir::Node::LetStmt(let_stmt) => Some(let_stmt), + _ => None, + } +} diff --git a/tests/ui/excessive_precision.fixed b/tests/ui/excessive_precision.fixed index 8a8c2e1939c8..698238f34365 100644 --- a/tests/ui/excessive_precision.fixed +++ b/tests/ui/excessive_precision.fixed @@ -101,4 +101,12 @@ fn main() { const _: f64 = 3.0; //~^ excessive_precision const _: f64 = 3.0000000000000000; + + // Overly specified constants + let _: f32 = 1.012_345_7; + //~^ excessive_precision + let _: f64 = 1.012_345_678_901_234_6; + //~^ excessive_precision + const _: f32 = 1.01234567890123456789012345678901234567890; + const _: f64 = 1.01234567890123456789012345678901234567890; } diff --git a/tests/ui/excessive_precision.rs b/tests/ui/excessive_precision.rs index 5dcf55cb9273..c8f4f79c1042 100644 --- a/tests/ui/excessive_precision.rs +++ b/tests/ui/excessive_precision.rs @@ -101,4 +101,12 @@ fn main() { const _: f64 = 3.0000000000000000e+00; //~^ excessive_precision const _: f64 = 3.0000000000000000; + + // Overly specified constants + let _: f32 = 1.01234567890123456789012345678901234567890; + //~^ excessive_precision + let _: f64 = 1.01234567890123456789012345678901234567890; + //~^ excessive_precision + const _: f32 = 1.01234567890123456789012345678901234567890; + const _: f64 = 1.01234567890123456789012345678901234567890; } diff --git a/tests/ui/excessive_precision.stderr b/tests/ui/excessive_precision.stderr index f5eeadf0c8cb..e4ddbd12f05e 100644 --- a/tests/ui/excessive_precision.stderr +++ b/tests/ui/excessive_precision.stderr @@ -192,5 +192,39 @@ LL - const _: f64 = 3.0000000000000000e+00; LL + const _: f64 = 3.0; | -error: aborting due to 16 previous errors +error: float has excessive precision + --> tests/ui/excessive_precision.rs:106:18 + | +LL | let _: f32 = 1.01234567890123456789012345678901234567890; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: consider making it a `const` item + --> tests/ui/excessive_precision.rs:106:5 + | +LL | let _: f32 = 1.01234567890123456789012345678901234567890; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider changing the type or truncating it to + | +LL - let _: f32 = 1.01234567890123456789012345678901234567890; +LL + let _: f32 = 1.012_345_7; + | + +error: float has excessive precision + --> tests/ui/excessive_precision.rs:108:18 + | +LL | let _: f64 = 1.01234567890123456789012345678901234567890; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: consider making it a `const` item + --> tests/ui/excessive_precision.rs:108:5 + | +LL | let _: f64 = 1.01234567890123456789012345678901234567890; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider changing the type or truncating it to + | +LL - let _: f64 = 1.01234567890123456789012345678901234567890; +LL + let _: f64 = 1.012_345_678_901_234_6; + | + +error: aborting due to 18 previous errors