Skip to content
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

Make approx_const MSRV aware #7629

Merged
merged 4 commits into from Sep 5, 2021
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
123 changes: 69 additions & 54 deletions clippy_lints/src/approx_const.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use clippy_utils::diagnostics::span_lint;
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::{meets_msrv, msrvs};
use rustc_ast::ast::{FloatTy, LitFloatType, LitKind};
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_semver::RustcVersion;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::symbol;
use std::f64::consts as f64;

Expand Down Expand Up @@ -36,68 +38,81 @@ declare_clippy_lint! {
"the approximate of a known float constant (in `std::fXX::consts`)"
}

// Tuples are of the form (constant, name, min_digits)
const KNOWN_CONSTS: [(f64, &str, usize); 18] = [
(f64::E, "E", 4),
(f64::FRAC_1_PI, "FRAC_1_PI", 4),
(f64::FRAC_1_SQRT_2, "FRAC_1_SQRT_2", 5),
(f64::FRAC_2_PI, "FRAC_2_PI", 5),
(f64::FRAC_2_SQRT_PI, "FRAC_2_SQRT_PI", 5),
(f64::FRAC_PI_2, "FRAC_PI_2", 5),
(f64::FRAC_PI_3, "FRAC_PI_3", 5),
(f64::FRAC_PI_4, "FRAC_PI_4", 5),
(f64::FRAC_PI_6, "FRAC_PI_6", 5),
(f64::FRAC_PI_8, "FRAC_PI_8", 5),
(f64::LN_10, "LN_10", 5),
(f64::LN_2, "LN_2", 5),
(f64::LOG10_E, "LOG10_E", 5),
(f64::LOG2_E, "LOG2_E", 5),
(f64::LOG2_10, "LOG2_10", 5),
(f64::LOG10_2, "LOG10_2", 5),
(f64::PI, "PI", 3),
(f64::SQRT_2, "SQRT_2", 5),
// Tuples are of the form (constant, name, min_digits, msrv)
const KNOWN_CONSTS: [(f64, &str, usize, Option<RustcVersion>); 18] = [
(f64::E, "E", 4, None),
(f64::FRAC_1_PI, "FRAC_1_PI", 4, None),
(f64::FRAC_1_SQRT_2, "FRAC_1_SQRT_2", 5, None),
(f64::FRAC_2_PI, "FRAC_2_PI", 5, None),
(f64::FRAC_2_SQRT_PI, "FRAC_2_SQRT_PI", 5, None),
(f64::FRAC_PI_2, "FRAC_PI_2", 5, None),
(f64::FRAC_PI_3, "FRAC_PI_3", 5, None),
(f64::FRAC_PI_4, "FRAC_PI_4", 5, None),
(f64::FRAC_PI_6, "FRAC_PI_6", 5, None),
(f64::FRAC_PI_8, "FRAC_PI_8", 5, None),
(f64::LN_2, "LN_2", 5, None),
(f64::LN_10, "LN_10", 5, None),
(f64::LOG2_10, "LOG2_10", 5, Some(msrvs::LOG2_10)),
(f64::LOG2_E, "LOG2_E", 5, None),
(f64::LOG10_2, "LOG10_2", 5, Some(msrvs::LOG10_2)),
(f64::LOG10_E, "LOG10_E", 5, None),
(f64::PI, "PI", 3, None),
(f64::SQRT_2, "SQRT_2", 5, None),
];

declare_lint_pass!(ApproxConstant => [APPROX_CONSTANT]);
pub struct ApproxConstant {
msrv: Option<RustcVersion>,
}

impl<'tcx> LateLintPass<'tcx> for ApproxConstant {
fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
if let ExprKind::Lit(lit) = &e.kind {
check_lit(cx, &lit.node, e);
impl ApproxConstant {
#[must_use]
pub fn new(msrv: Option<RustcVersion>) -> Self {
Self { msrv }
}

fn check_lit(&self, cx: &LateContext<'_>, lit: &LitKind, e: &Expr<'_>) {
match *lit {
LitKind::Float(s, LitFloatType::Suffixed(fty)) => match fty {
FloatTy::F32 => self.check_known_consts(cx, e, s, "f32"),
FloatTy::F64 => self.check_known_consts(cx, e, s, "f64"),
},
LitKind::Float(s, LitFloatType::Unsuffixed) => self.check_known_consts(cx, e, s, "f{32, 64}"),
_ => (),
}
}
}

fn check_lit(cx: &LateContext<'_>, lit: &LitKind, e: &Expr<'_>) {
match *lit {
LitKind::Float(s, LitFloatType::Suffixed(fty)) => match fty {
FloatTy::F32 => check_known_consts(cx, e, s, "f32"),
FloatTy::F64 => check_known_consts(cx, e, s, "f64"),
},
LitKind::Float(s, LitFloatType::Unsuffixed) => check_known_consts(cx, e, s, "f{32, 64}"),
_ => (),
fn check_known_consts(&self, cx: &LateContext<'_>, e: &Expr<'_>, s: symbol::Symbol, module: &str) {
let s = s.as_str();
if s.parse::<f64>().is_ok() {
for &(constant, name, min_digits, msrv) in &KNOWN_CONSTS {
if is_approx_const(constant, &s, min_digits)
&& msrv.as_ref().map_or(true, |msrv| meets_msrv(self.msrv.as_ref(), msrv))
{
span_lint_and_help(
cx,
APPROX_CONSTANT,
e.span,
&format!("approximate value of `{}::consts::{}` found", module, &name),
None,
"consider using the constant directly",
);
return;
}
}
}
}
}

fn check_known_consts(cx: &LateContext<'_>, e: &Expr<'_>, s: symbol::Symbol, module: &str) {
let s = s.as_str();
if s.parse::<f64>().is_ok() {
for &(constant, name, min_digits) in &KNOWN_CONSTS {
if is_approx_const(constant, &s, min_digits) {
span_lint(
cx,
APPROX_CONSTANT,
e.span,
&format!(
"approximate value of `{}::consts::{}` found. \
Consider using it directly",
module, &name
),
);
return;
}
impl_lint_pass!(ApproxConstant => [APPROX_CONSTANT]);

impl<'tcx> LateLintPass<'tcx> for ApproxConstant {
fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
if let ExprKind::Lit(lit) = &e.kind {
self.check_lit(cx, &lit.node, e);
}
}

extract_msrv_attr!(LateContext);
}

/// Returns `false` if the number of significant figures in `value` are
Expand Down
2 changes: 1 addition & 1 deletion clippy_lints/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1865,7 +1865,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_late_pass(|| Box::new(needless_bool::NeedlessBool));
store.register_late_pass(|| Box::new(needless_bool::BoolComparison));
store.register_late_pass(|| Box::new(needless_for_each::NeedlessForEach));
store.register_late_pass(|| Box::new(approx_const::ApproxConstant));
store.register_late_pass(|| Box::new(misc::MiscLints));
store.register_late_pass(|| Box::new(eta_reduction::EtaReduction));
store.register_late_pass(|| Box::new(identity_op::IdentityOp));
Expand Down Expand Up @@ -1894,6 +1893,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
});

let avoid_breaking_exported_api = conf.avoid_breaking_exported_api;
store.register_late_pass(move || Box::new(approx_const::ApproxConstant::new(msrv)));
store.register_late_pass(move || Box::new(methods::Methods::new(avoid_breaking_exported_api, msrv)));
store.register_late_pass(move || Box::new(matches::Matches::new(msrv)));
store.register_early_pass(move || Box::new(manual_non_exhaustive::ManualNonExhaustive::new(msrv)));
Expand Down
2 changes: 1 addition & 1 deletion clippy_lints/src/utils/conf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ define_Conf! {
///
/// Suppress lints whenever the suggested change would cause breakage for other crates.
(avoid_breaking_exported_api: bool = true),
/// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE.
/// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT.
///
/// The minimum rust version that the project supports
(msrv: Option<String> = None),
Expand Down
1 change: 1 addition & 0 deletions clippy_utils/src/msrvs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ msrv_aliases! {
1,50,0 { BOOL_THEN }
1,46,0 { CONST_IF_MATCH }
1,45,0 { STR_STRIP_PREFIX }
1,43,0 { LOG2_10, LOG10_2 }
1,42,0 { MATCHES_MACRO }
1,41,0 { RE_REBALANCING_COHERENCE, RESULT_MAP_OR_ELSE }
1,40,0 { MEM_TAKE, NON_EXHAUSTIVE, OPTION_AS_DEREF }
Expand Down
83 changes: 62 additions & 21 deletions tests/ui/approx_const.stderr
Original file line number Diff line number Diff line change
@@ -1,130 +1,171 @@
error: approximate value of `f{32, 64}::consts::E` found. Consider using it directly
error: approximate value of `f{32, 64}::consts::E` found
--> $DIR/approx_const.rs:4:16
|
LL | let my_e = 2.7182;
| ^^^^^^
|
= note: `-D clippy::approx-constant` implied by `-D warnings`
= help: consider using the constant directly

error: approximate value of `f{32, 64}::consts::E` found. Consider using it directly
error: approximate value of `f{32, 64}::consts::E` found
--> $DIR/approx_const.rs:5:20
|
LL | let almost_e = 2.718;
| ^^^^^
|
= help: consider using the constant directly

error: approximate value of `f{32, 64}::consts::FRAC_1_PI` found. Consider using it directly
error: approximate value of `f{32, 64}::consts::FRAC_1_PI` found
--> $DIR/approx_const.rs:8:24
|
LL | let my_1_frac_pi = 0.3183;
| ^^^^^^
|
= help: consider using the constant directly

error: approximate value of `f{32, 64}::consts::FRAC_1_SQRT_2` found. Consider using it directly
error: approximate value of `f{32, 64}::consts::FRAC_1_SQRT_2` found
--> $DIR/approx_const.rs:11:28
|
LL | let my_frac_1_sqrt_2 = 0.70710678;
| ^^^^^^^^^^
|
= help: consider using the constant directly

error: approximate value of `f{32, 64}::consts::FRAC_1_SQRT_2` found. Consider using it directly
error: approximate value of `f{32, 64}::consts::FRAC_1_SQRT_2` found
--> $DIR/approx_const.rs:12:32
|
LL | let almost_frac_1_sqrt_2 = 0.70711;
| ^^^^^^^
|
= help: consider using the constant directly

error: approximate value of `f{32, 64}::consts::FRAC_2_PI` found. Consider using it directly
error: approximate value of `f{32, 64}::consts::FRAC_2_PI` found
--> $DIR/approx_const.rs:15:24
|
LL | let my_frac_2_pi = 0.63661977;
| ^^^^^^^^^^
|
= help: consider using the constant directly

error: approximate value of `f{32, 64}::consts::FRAC_2_SQRT_PI` found. Consider using it directly
error: approximate value of `f{32, 64}::consts::FRAC_2_SQRT_PI` found
--> $DIR/approx_const.rs:18:27
|
LL | let my_frac_2_sq_pi = 1.128379;
| ^^^^^^^^
|
= help: consider using the constant directly

error: approximate value of `f{32, 64}::consts::FRAC_PI_2` found. Consider using it directly
error: approximate value of `f{32, 64}::consts::FRAC_PI_2` found
--> $DIR/approx_const.rs:21:24
|
LL | let my_frac_pi_2 = 1.57079632679;
| ^^^^^^^^^^^^^
|
= help: consider using the constant directly

error: approximate value of `f{32, 64}::consts::FRAC_PI_3` found. Consider using it directly
error: approximate value of `f{32, 64}::consts::FRAC_PI_3` found
--> $DIR/approx_const.rs:24:24
|
LL | let my_frac_pi_3 = 1.04719755119;
| ^^^^^^^^^^^^^
|
= help: consider using the constant directly

error: approximate value of `f{32, 64}::consts::FRAC_PI_4` found. Consider using it directly
error: approximate value of `f{32, 64}::consts::FRAC_PI_4` found
--> $DIR/approx_const.rs:27:24
|
LL | let my_frac_pi_4 = 0.785398163397;
| ^^^^^^^^^^^^^^
|
= help: consider using the constant directly

error: approximate value of `f{32, 64}::consts::FRAC_PI_6` found. Consider using it directly
error: approximate value of `f{32, 64}::consts::FRAC_PI_6` found
--> $DIR/approx_const.rs:30:24
|
LL | let my_frac_pi_6 = 0.523598775598;
| ^^^^^^^^^^^^^^
|
= help: consider using the constant directly

error: approximate value of `f{32, 64}::consts::FRAC_PI_8` found. Consider using it directly
error: approximate value of `f{32, 64}::consts::FRAC_PI_8` found
--> $DIR/approx_const.rs:33:24
|
LL | let my_frac_pi_8 = 0.3926990816987;
| ^^^^^^^^^^^^^^^
|
= help: consider using the constant directly

error: approximate value of `f{32, 64}::consts::LN_10` found. Consider using it directly
error: approximate value of `f{32, 64}::consts::LN_10` found
--> $DIR/approx_const.rs:36:20
|
LL | let my_ln_10 = 2.302585092994046;
| ^^^^^^^^^^^^^^^^^
|
= help: consider using the constant directly

error: approximate value of `f{32, 64}::consts::LN_2` found. Consider using it directly
error: approximate value of `f{32, 64}::consts::LN_2` found
--> $DIR/approx_const.rs:39:19
|
LL | let my_ln_2 = 0.6931471805599453;
| ^^^^^^^^^^^^^^^^^^
|
= help: consider using the constant directly

error: approximate value of `f{32, 64}::consts::LOG10_E` found. Consider using it directly
error: approximate value of `f{32, 64}::consts::LOG10_E` found
--> $DIR/approx_const.rs:42:22
|
LL | let my_log10_e = 0.4342944819032518;
| ^^^^^^^^^^^^^^^^^^
|
= help: consider using the constant directly

error: approximate value of `f{32, 64}::consts::LOG2_E` found. Consider using it directly
error: approximate value of `f{32, 64}::consts::LOG2_E` found
--> $DIR/approx_const.rs:45:21
|
LL | let my_log2_e = 1.4426950408889634;
| ^^^^^^^^^^^^^^^^^^
|
= help: consider using the constant directly

error: approximate value of `f{32, 64}::consts::LOG2_10` found. Consider using it directly
error: approximate value of `f{32, 64}::consts::LOG2_10` found
--> $DIR/approx_const.rs:48:19
|
LL | let log2_10 = 3.321928094887362;
| ^^^^^^^^^^^^^^^^^
|
= help: consider using the constant directly

error: approximate value of `f{32, 64}::consts::LOG10_2` found. Consider using it directly
error: approximate value of `f{32, 64}::consts::LOG10_2` found
--> $DIR/approx_const.rs:51:19
|
LL | let log10_2 = 0.301029995663981;
| ^^^^^^^^^^^^^^^^^
|
= help: consider using the constant directly

error: approximate value of `f{32, 64}::consts::PI` found. Consider using it directly
error: approximate value of `f{32, 64}::consts::PI` found
--> $DIR/approx_const.rs:54:17
|
LL | let my_pi = 3.1415;
| ^^^^^^
|
= help: consider using the constant directly

error: approximate value of `f{32, 64}::consts::PI` found. Consider using it directly
error: approximate value of `f{32, 64}::consts::PI` found
--> $DIR/approx_const.rs:55:21
|
LL | let almost_pi = 3.14;
| ^^^^
|
= help: consider using the constant directly

error: approximate value of `f{32, 64}::consts::SQRT_2` found. Consider using it directly
error: approximate value of `f{32, 64}::consts::SQRT_2` found
--> $DIR/approx_const.rs:58:18
|
LL | let my_sq2 = 1.4142;
| ^^^^^^
|
= help: consider using the constant directly

error: aborting due to 21 previous errors

5 changes: 5 additions & 0 deletions tests/ui/min_rust_version_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@

use std::ops::{Deref, RangeFrom};

fn approx_const() {
let log2_10 = 3.321928094887362;
let log10_2 = 0.301029995663981;
}

fn cloned_instead_of_copied() {
let _ = [1].iter().cloned();
}
Expand Down
Loading