Skip to content

Supress excessive_precision when constants are overly precise #15193

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 29 additions & 1 deletion clippy_lints/src/float_literal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
///
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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,
}
}
8 changes: 8 additions & 0 deletions tests/ui/excessive_precision.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
8 changes: 8 additions & 0 deletions tests/ui/excessive_precision.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
36 changes: 35 additions & 1 deletion tests/ui/excessive_precision.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^

Ideally I would like this to only underline the let keyword, I couldn't find that span in the HIR node, any help or pointer is appreciated.

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

Loading