Skip to content

Commit 093b6e5

Browse files
committed
Fix approx_const for some new cases
Improved naming and comment
1 parent d964e55 commit 093b6e5

File tree

3 files changed

+74
-8
lines changed

3 files changed

+74
-8
lines changed

clippy_lints/src/approx_const.rs

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,11 @@ impl LateLintPass<'_> for ApproxConstant {
9292
impl ApproxConstant {
9393
fn check_known_consts(&self, cx: &LateContext<'_>, span: Span, s: symbol::Symbol, module: &str) {
9494
let s = s.as_str();
95-
if s.parse::<f64>().is_ok() {
95+
if let Ok(maybe_constant) = s.parse::<f64>() {
9696
for &(constant, name, min_digits, msrv) in &KNOWN_CONSTS {
97-
if is_approx_const(constant, s, min_digits) && msrv.is_none_or(|msrv| self.msrv.meets(cx, msrv)) {
97+
if is_approx_const(constant, s, maybe_constant, min_digits)
98+
&& msrv.is_none_or(|msrv| self.msrv.meets(cx, msrv))
99+
{
98100
span_lint_and_help(
99101
cx,
100102
APPROX_CONSTANT,
@@ -112,18 +114,35 @@ impl ApproxConstant {
112114

113115
impl_lint_pass!(ApproxConstant => [APPROX_CONSTANT]);
114116

117+
fn count_digits_after_dot(input: &str) -> usize {
118+
input
119+
.char_indices()
120+
.find(|(_, ch)| *ch == '.')
121+
.map_or(0, |(i, _)| input.len() - i - 1)
122+
}
123+
115124
/// Returns `false` if the number of significant figures in `value` are
116125
/// less than `min_digits`; otherwise, returns true if `value` is equal
117-
/// to `constant`, rounded to the number of digits present in `value`.
126+
/// to `constant`, rounded to the number of significant digits present in `value`.
118127
#[must_use]
119-
fn is_approx_const(constant: f64, value: &str, min_digits: usize) -> bool {
128+
fn is_approx_const(constant: f64, value: &str, f_value: f64, min_digits: usize) -> bool {
120129
if value.len() <= min_digits {
130+
// The value is not precise enough
121131
false
122-
} else if constant.to_string().starts_with(value) {
123-
// The value is a truncated constant
132+
} else if f_value.to_string().len() > min_digits && constant.to_string().starts_with(&f_value.to_string()) {
133+
// The value represents the same value
124134
true
125135
} else {
126-
let round_const = format!("{constant:.*}", value.len() - 2);
136+
// The value is a truncated constant
137+
138+
// Print constant with numeric formatting (`0`), with the length of `value` as minimum width
139+
// (`value_len$`), and with the same precision as `value` (`.value_prec$`).
140+
// See https://doc.rust-lang.org/std/fmt/index.html.
141+
let round_const = format!(
142+
"{constant:0value_len$.value_prec$}",
143+
value_len = value.len(),
144+
value_prec = count_digits_after_dot(value)
145+
);
127146
value == round_const
128147
}
129148
}

tests/ui/approx_const.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,4 +106,19 @@ fn main() {
106106
//~^ approx_constant
107107

108108
let no_tau = 6.3;
109+
110+
// issue #15194
111+
#[allow(clippy::excessive_precision)]
112+
let x: f64 = 3.1415926535897932384626433832;
113+
//~^ approx_constant
114+
115+
#[allow(clippy::excessive_precision)]
116+
let _: f64 = 003.14159265358979311599796346854418516159057617187500;
117+
//~^ approx_constant
118+
119+
let almost_frac_1_sqrt_2 = 00.70711;
120+
//~^ approx_constant
121+
122+
let almost_frac_1_sqrt_2 = 00.707_11;
123+
//~^ approx_constant
109124
}

tests/ui/approx_const.stderr

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,5 +184,37 @@ LL | let almost_tau = 6.28;
184184
|
185185
= help: consider using the constant directly
186186

187-
error: aborting due to 23 previous errors
187+
error: approximate value of `f{32, 64}::consts::PI` found
188+
--> tests/ui/approx_const.rs:112:18
189+
|
190+
LL | let x: f64 = 3.1415926535897932384626433832;
191+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
192+
|
193+
= help: consider using the constant directly
194+
195+
error: approximate value of `f{32, 64}::consts::PI` found
196+
--> tests/ui/approx_const.rs:116:18
197+
|
198+
LL | let _: f64 = 003.14159265358979311599796346854418516159057617187500;
199+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
200+
|
201+
= help: consider using the constant directly
202+
203+
error: approximate value of `f{32, 64}::consts::FRAC_1_SQRT_2` found
204+
--> tests/ui/approx_const.rs:119:32
205+
|
206+
LL | let almost_frac_1_sqrt_2 = 00.70711;
207+
| ^^^^^^^^
208+
|
209+
= help: consider using the constant directly
210+
211+
error: approximate value of `f{32, 64}::consts::FRAC_1_SQRT_2` found
212+
--> tests/ui/approx_const.rs:122:32
213+
|
214+
LL | let almost_frac_1_sqrt_2 = 00.707_11;
215+
| ^^^^^^^^^
216+
|
217+
= help: consider using the constant directly
218+
219+
error: aborting due to 27 previous errors
188220

0 commit comments

Comments
 (0)