Skip to content
Merged
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6712,6 +6712,7 @@ Released 2018-09-13
[`check-inconsistent-struct-field-initializers`]: https://doc.rust-lang.org/clippy/lint_configuration.html#check-inconsistent-struct-field-initializers
[`check-private-items`]: https://doc.rust-lang.org/clippy/lint_configuration.html#check-private-items
[`cognitive-complexity-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#cognitive-complexity-threshold
[`const-literal-digits-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#const-literal-digits-threshold
[`disallowed-macros`]: https://doc.rust-lang.org/clippy/lint_configuration.html#disallowed-macros
[`disallowed-methods`]: https://doc.rust-lang.org/clippy/lint_configuration.html#disallowed-methods
[`disallowed-names`]: https://doc.rust-lang.org/clippy/lint_configuration.html#disallowed-names
Expand Down
10 changes: 10 additions & 0 deletions book/src/lint_configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,16 @@ The maximum cognitive complexity a function can have
* [`cognitive_complexity`](https://rust-lang.github.io/rust-clippy/master/index.html#cognitive_complexity)


## `const-literal-digits-threshold`
The minimum digits a const float literal must have to supress the `excessive_precicion` lint

**Default Value:** `30`

---
**Affected lints:**
* [`excessive_precision`](https://rust-lang.github.io/rust-clippy/master/index.html#excessive_precision)


## `disallowed-macros`
The list of disallowed macros, written as fully qualified paths.

Expand Down
3 changes: 3 additions & 0 deletions clippy_config/src/conf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,9 @@ define_Conf! {
/// The maximum cognitive complexity a function can have
#[lints(cognitive_complexity)]
cognitive_complexity_threshold: u64 = 25,
/// The minimum digits a const float literal must have to supress the `excessive_precicion` lint
#[lints(excessive_precision)]
const_literal_digits_threshold: usize = 30,
/// DEPRECATED LINT: CYCLOMATIC_COMPLEXITY.
///
/// Use the Cognitive Complexity lint instead.
Expand Down
45 changes: 41 additions & 4 deletions clippy_lints/src/float_literal.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
use clippy_config::Conf;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::numeric_literal;
use clippy_utils::{ExprUseNode, expr_use_ctxt, numeric_literal};
use rustc_ast::ast::{LitFloatType, LitKind};
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::{self, FloatTy};
use rustc_session::declare_lint_pass;
use rustc_session::impl_lint_pass;
use std::fmt;

declare_clippy_lint! {
/// ### What it does
/// Checks for float literals with a precision greater
/// than that supported by the underlying type.
///
/// The lint is suppressed for literals with over `const_literal_digits_threshold` digits.
///
/// ### Why is this bad?
/// Rust will truncate the literal silently.
///
Expand Down Expand Up @@ -58,7 +61,21 @@ declare_clippy_lint! {
"lossy whole number float literals"
}

declare_lint_pass!(FloatLiteral => [EXCESSIVE_PRECISION, LOSSY_FLOAT_LITERAL]);
pub struct FloatLiteral {
const_literal_digits_threshold: usize,
}

impl_lint_pass!(FloatLiteral => [
EXCESSIVE_PRECISION, LOSSY_FLOAT_LITERAL
]);

impl FloatLiteral {
pub fn new(conf: &'static Conf) -> Self {
Self {
const_literal_digits_threshold: conf.const_literal_digits_threshold,
}
}
}

impl<'tcx> LateLintPass<'tcx> for FloatLiteral {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
Expand Down Expand Up @@ -126,13 +143,25 @@ 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 >= self.const_literal_digits_threshold
&& matches!(expr_use_ctxt(cx, expr).use_node(cx), ExprUseNode::ConstStatic(_))
{
// 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 >= self.const_literal_digits_threshold
&& 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 +225,11 @@ impl FloatFormat {
}
}
}

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,
}
}
2 changes: 1 addition & 1 deletion clippy_lints/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,7 @@ pub fn register_lint_passes(store: &mut rustc_lint::LintStore, conf: &'static Co
store.register_late_pass(move |_| Box::new(types::Types::new(conf)));
store.register_late_pass(move |_| Box::new(booleans::NonminimalBool::new(conf)));
store.register_late_pass(|_| Box::new(enum_clike::UnportableVariant));
store.register_late_pass(|_| Box::new(float_literal::FloatLiteral));
store.register_late_pass(move |_| Box::new(float_literal::FloatLiteral::new(conf)));
store.register_late_pass(|_| Box::new(ptr::Ptr));
store.register_late_pass(|_| Box::new(needless_bool::NeedlessBool));
store.register_late_pass(|_| Box::new(bool_comparison::BoolComparison));
Expand Down
1 change: 1 addition & 0 deletions tests/ui-toml/excessive_precision/clippy.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
const-literal-digits-threshold = 20
38 changes: 38 additions & 0 deletions tests/ui-toml/excessive_precision/excessive_precision.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#![warn(clippy::excessive_precision)]
#![allow(
dead_code,
overflowing_literals,
unused_variables,
clippy::print_literal,
clippy::useless_vec
)]

fn main() {
// 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.012345678901234567890;
const _: f64 = 1.012345678901234567890;

static STATIC1: f32 = 1.012345678901234567890;
static STATIC2: f64 = 1.012345678901234567890;

static mut STATIC_MUT1: f32 = 1.012345678901234567890;
static mut STATIC_MUT2: f64 = 1.012345678901234567890;
}

trait ExcessivelyPreciseTrait {
// Overly specified constants
const GOOD1: f32 = 1.012345678901234567890;
const GOOD2: f64 = 1.012345678901234567890;
}

struct ExcessivelyPreciseStruct;

impl ExcessivelyPreciseStruct {
// Overly specified constants
const GOOD1: f32 = 1.012345678901234567890;
const GOOD2: f64 = 1.012345678901234567890;
}
38 changes: 38 additions & 0 deletions tests/ui-toml/excessive_precision/excessive_precision.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#![warn(clippy::excessive_precision)]
#![allow(
dead_code,
overflowing_literals,
unused_variables,
clippy::print_literal,
clippy::useless_vec
)]

fn main() {
// Overly specified constants
let _: f32 = 1.012345678901234567890;
//~^ excessive_precision
let _: f64 = 1.012345678901234567890;
//~^ excessive_precision
const _: f32 = 1.012345678901234567890;
const _: f64 = 1.012345678901234567890;

static STATIC1: f32 = 1.012345678901234567890;
static STATIC2: f64 = 1.012345678901234567890;

static mut STATIC_MUT1: f32 = 1.012345678901234567890;
static mut STATIC_MUT2: f64 = 1.012345678901234567890;
}

trait ExcessivelyPreciseTrait {
// Overly specified constants
const GOOD1: f32 = 1.012345678901234567890;
const GOOD2: f64 = 1.012345678901234567890;
}

struct ExcessivelyPreciseStruct;

impl ExcessivelyPreciseStruct {
// Overly specified constants
const GOOD1: f32 = 1.012345678901234567890;
const GOOD2: f64 = 1.012345678901234567890;
}
38 changes: 38 additions & 0 deletions tests/ui-toml/excessive_precision/excessive_precision.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
error: float has excessive precision
--> tests/ui-toml/excessive_precision/excessive_precision.rs:12:18
|
LL | let _: f32 = 1.012345678901234567890;
| ^^^^^^^^^^^^^^^^^^^^^^^
|
note: consider making it a `const` item
--> tests/ui-toml/excessive_precision/excessive_precision.rs:12:5
|
LL | let _: f32 = 1.012345678901234567890;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: `-D clippy::excessive-precision` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::excessive_precision)]`
help: consider changing the type or truncating it to
|
LL - let _: f32 = 1.012345678901234567890;
LL + let _: f32 = 1.012_345_7;
|

error: float has excessive precision
--> tests/ui-toml/excessive_precision/excessive_precision.rs:14:18
|
LL | let _: f64 = 1.012345678901234567890;
| ^^^^^^^^^^^^^^^^^^^^^^^
|
note: consider making it a `const` item
--> tests/ui-toml/excessive_precision/excessive_precision.rs:14:5
|
LL | let _: f64 = 1.012345678901234567890;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: consider changing the type or truncating it to
|
LL - let _: f64 = 1.012345678901234567890;
LL + let _: f64 = 1.012_345_678_901_234_6;
|

error: aborting due to 2 previous errors

3 changes: 3 additions & 0 deletions tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect
check-inconsistent-struct-field-initializers
check-private-items
cognitive-complexity-threshold
const-literal-digits-threshold
disallowed-macros
disallowed-methods
disallowed-names
Expand Down Expand Up @@ -129,6 +130,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect
check-inconsistent-struct-field-initializers
check-private-items
cognitive-complexity-threshold
const-literal-digits-threshold
disallowed-macros
disallowed-methods
disallowed-names
Expand Down Expand Up @@ -223,6 +225,7 @@ error: error reading Clippy's configuration file: unknown field `allow_mixed_uni
check-inconsistent-struct-field-initializers
check-private-items
cognitive-complexity-threshold
const-literal-digits-threshold
disallowed-macros
disallowed-methods
disallowed-names
Expand Down
45 changes: 44 additions & 1 deletion tests/ui/excessive_precision.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,16 @@
overflowing_literals,
unused_variables,
clippy::print_literal,
clippy::useless_vec
clippy::useless_vec,
clippy::approx_constant
)]

macro_rules! make_pi {
($i:ident : $t:ty) => {
const $i: $t = 3.14159265358979323846264338327950288419716939937510582097494459230781640628;
};
}

fn main() {
// Consts
const GOOD32: f32 = 0.123_456;
Expand Down Expand Up @@ -101,4 +108,40 @@ 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;

static STATIC1: f32 = 1.01234567890123456789012345678901234567890;
static STATIC2: f64 = 1.01234567890123456789012345678901234567890;

static mut STATIC_MUT1: f32 = 1.01234567890123456789012345678901234567890;
static mut STATIC_MUT2: f64 = 1.01234567890123456789012345678901234567890;

// From issue #13855
let gamma = 0.577_215_664_901_532_9;
//~^ excessive_precision
const GAMMA: f64 = 0.5772156649015328606065120900824024310421;

make_pi!(P32: f32);
make_pi!(P64: f64);
}

trait ExcessivelyPreciseTrait {
// Overly specified constants
const GOOD1: f32 = 1.01234567890123456789012345678901234567890;
const GOOD2: f64 = 1.01234567890123456789012345678901234567890;
}

struct ExcessivelyPreciseStruct;

impl ExcessivelyPreciseStruct {
// Overly specified constants
const GOOD1: f32 = 1.01234567890123456789012345678901234567890;
const GOOD2: f64 = 1.01234567890123456789012345678901234567890;
}
45 changes: 44 additions & 1 deletion tests/ui/excessive_precision.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,16 @@
overflowing_literals,
unused_variables,
clippy::print_literal,
clippy::useless_vec
clippy::useless_vec,
clippy::approx_constant
)]

macro_rules! make_pi {
($i:ident : $t:ty) => {
const $i: $t = 3.14159265358979323846264338327950288419716939937510582097494459230781640628;
};
}

fn main() {
// Consts
const GOOD32: f32 = 0.123_456;
Expand Down Expand Up @@ -101,4 +108,40 @@ 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;

static STATIC1: f32 = 1.01234567890123456789012345678901234567890;
static STATIC2: f64 = 1.01234567890123456789012345678901234567890;

static mut STATIC_MUT1: f32 = 1.01234567890123456789012345678901234567890;
static mut STATIC_MUT2: f64 = 1.01234567890123456789012345678901234567890;

// From issue #13855
let gamma = 0.5772156649015328606065120900824024310421;
//~^ excessive_precision
const GAMMA: f64 = 0.5772156649015328606065120900824024310421;

make_pi!(P32: f32);
make_pi!(P64: f64);
}

trait ExcessivelyPreciseTrait {
// Overly specified constants
const GOOD1: f32 = 1.01234567890123456789012345678901234567890;
const GOOD2: f64 = 1.01234567890123456789012345678901234567890;
}

struct ExcessivelyPreciseStruct;

impl ExcessivelyPreciseStruct {
// Overly specified constants
const GOOD1: f32 = 1.01234567890123456789012345678901234567890;
const GOOD2: f64 = 1.01234567890123456789012345678901234567890;
}
Loading