Skip to content

Commit 66165c6

Browse files
authored
Merge pull request #2720 from estk/fix-dot-zero
Fix 1x...xx.0 false positive.
2 parents 0557359 + d4b536f commit 66165c6

File tree

4 files changed

+108
-68
lines changed

4 files changed

+108
-68
lines changed

clippy_lints/src/excessive_precision.rs

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,16 @@ impl ExcessivePrecision {
6969
fn check(&self, sym: &Symbol, fty: &FloatTy) -> Option<String> {
7070
let max = max_digits(fty);
7171
let sym_str = sym.as_str();
72-
let formatter = FloatFormat::new(&sym_str);
73-
let digits = count_digits(&sym_str);
72+
if dot_zero_exclusion(&sym_str) {
73+
return None
74+
}
7475
// Try to bail out if the float is for sure fine.
7576
// If its within the 2 decimal digits of being out of precision we
7677
// check if the parsed representation is the same as the string
7778
// since we'll need the truncated string anyway.
79+
let digits = count_digits(&sym_str);
7880
if digits > max as usize {
81+
let formatter = FloatFormat::new(&sym_str);
7982
let sr = match *fty {
8083
FloatTy::F32 => sym_str.parse::<f32>().map(|f| formatter.format(f)),
8184
FloatTy::F64 => sym_str.parse::<f64>().map(|f| formatter.format(f)),
@@ -86,22 +89,42 @@ impl ExcessivePrecision {
8689
if sym_str == s {
8790
None
8891
} else {
89-
Some(s)
92+
let di = super::literal_representation::DigitInfo::new(&s, true);
93+
Some(di.grouping_hint())
9094
}
9195
} else {
9296
None
9397
}
9498
}
9599
}
96100

101+
/// Should we exclude the float because it has a .0 suffix
102+
/// Ex 1_000_000_000.0
103+
fn dot_zero_exclusion(s: &str) -> bool {
104+
if let Some(after_dec) = s.split('.').nth(1) {
105+
let mut decpart = after_dec
106+
.chars()
107+
.take_while(|c| *c != 'e' || *c != 'E');
108+
109+
match decpart.next() {
110+
Some('0') => decpart.count() == 0,
111+
_ => false,
112+
}
113+
} else {
114+
false
115+
}
116+
}
117+
97118
fn max_digits(fty: &FloatTy) -> u32 {
98119
match fty {
99120
FloatTy::F32 => f32::DIGITS,
100121
FloatTy::F64 => f64::DIGITS,
101122
}
102123
}
103124

125+
/// Counts the digits excluding leading zeros
104126
fn count_digits(s: &str) -> usize {
127+
// Note that s does not contain the f32/64 suffix
105128
s.chars()
106129
.filter(|c| *c != '-' || *c != '.')
107130
.take_while(|c| *c != 'e' || *c != 'E')

clippy_lints/src/literal_representation.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ declare_clippy_lint! {
8181
}
8282

8383
#[derive(Debug, PartialEq)]
84-
enum Radix {
84+
pub(super) enum Radix {
8585
Binary,
8686
Octal,
8787
Decimal,
@@ -99,7 +99,7 @@ impl Radix {
9999
}
100100

101101
#[derive(Debug)]
102-
struct DigitInfo<'a> {
102+
pub(super) struct DigitInfo<'a> {
103103
/// Characters of a literal between the radix prefix and type suffix.
104104
pub digits: &'a str,
105105
/// Which radix the literal was represented in.
@@ -160,7 +160,7 @@ impl<'a> DigitInfo<'a> {
160160
}
161161

162162
/// Returns digits grouped in a sensible way.
163-
fn grouping_hint(&self) -> String {
163+
pub fn grouping_hint(&self) -> String {
164164
let group_size = self.radix.suggest_grouping();
165165
if self.digits.contains('.') {
166166
let mut parts = self.digits.split('.');

tests/ui/excessive_precision.rs

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,45 +3,50 @@
33
#![allow(print_literal)]
44

55
fn main() {
6-
// TODO add prefix tests
76
// Consts
8-
const GOOD32_SUF: f32 = 0.123_456_f32;
97
const GOOD32: f32 = 0.123_456;
108
const GOOD32_SM: f32 = 0.000_000_000_1;
9+
const GOOD32_DOT: f32 = 10_000_000_000.0;
10+
const GOOD32_EDGE: f32 = 1.000_000_8;
1111
const GOOD64: f64 = 0.123_456_789_012;
1212
const GOOD64_SM: f32 = 0.000_000_000_000_000_1;
13+
const GOOD64_DOT: f32 = 10_000_000_000_000_000.0;
1314

1415
const BAD32_1: f32 = 0.123_456_789_f32;
1516
const BAD32_2: f32 = 0.123_456_789;
1617
const BAD32_3: f32 = 0.100_000_000_000_1;
18+
const BAD32_EDGE: f32 = 1.000_000_9;
1719

1820
const BAD64_1: f64 = 0.123_456_789_012_345_67f64;
1921
const BAD64_2: f64 = 0.123_456_789_012_345_67;
2022
const BAD64_3: f64 = 0.100_000_000_000_000_000_1;
2123

22-
// Literal
24+
// Literal as param
2325
println!("{}", 8.888_888_888_888_888_888_888);
2426

25-
// TODO add inferred type tests for f32
26-
// TODO add tests cases exactly on the edge
27+
// // TODO add inferred type tests for f32
2728
// Locals
2829
let good32: f32 = 0.123_456_f32;
2930
let good32_2: f32 = 0.123_456;
3031

31-
let good64: f64 = 0.123_456_789_012f64;
3232
let good64: f64 = 0.123_456_789_012;
33-
let good64_2 = 0.123_456_789_012;
33+
let good64_suf: f64 = 0.123_456_789_012f64;
34+
let good64_inf = 0.123_456_789_012;
3435

35-
let bad32_1: f32 = 1.123_456_789_f32;
36-
let bad32_2: f32 = 1.123_456_789;
36+
let bad32: f32 = 1.123_456_789;
37+
let bad32_suf: f32 = 1.123_456_789_f32;
38+
let bad32_inf = 1.123_456_789_f32;
3739

38-
let bad64_1: f64 = 0.123_456_789_012_345_67f64;
39-
let bad64_2: f64 = 0.123_456_789_012_345_67;
40-
let bad64_3 = 0.123_456_789_012_345_67;
40+
let bad64: f64 = 0.123_456_789_012_345_67;
41+
let bad64_suf: f64 = 0.123_456_789_012_345_67f64;
42+
let bad64_inf = 0.123_456_789_012_345_67;
4143

42-
// TODO Vectors / nested vectors
43-
let vec32: Vec<f32> = vec![0.123_456_789];
44-
let vec64: Vec<f64> = vec![0.123_456_789_123_456_789];
44+
// Vectors
45+
let good_vec32: Vec<f32> = vec![0.123_456];
46+
let good_vec64: Vec<f64> = vec![0.123_456_789];
47+
48+
let bad_vec32: Vec<f32> = vec![0.123_456_789];
49+
let bad_vec64: Vec<f64> = vec![0.123_456_789_123_456_789];
4550

4651
// Exponential float notation
4752
let good_e32: f32 = 1e-10;

tests/ui/excessive_precision.stderr

Lines changed: 59 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,100 +1,112 @@
11
error: float has excessive precision
2-
--> $DIR/excessive_precision.rs:14:26
2+
--> $DIR/excessive_precision.rs:15:26
33
|
4-
14 | const BAD32_1: f32 = 0.123_456_789_f32;
5-
| ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.12345679`
4+
15 | const BAD32_1: f32 = 0.123_456_789_f32;
5+
| ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_79`
66
|
77
= note: `-D excessive-precision` implied by `-D warnings`
88

99
error: float has excessive precision
10-
--> $DIR/excessive_precision.rs:15:26
10+
--> $DIR/excessive_precision.rs:16:26
1111
|
12-
15 | const BAD32_2: f32 = 0.123_456_789;
13-
| ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.12345679`
12+
16 | const BAD32_2: f32 = 0.123_456_789;
13+
| ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_79`
1414

1515
error: float has excessive precision
16-
--> $DIR/excessive_precision.rs:16:26
16+
--> $DIR/excessive_precision.rs:17:26
1717
|
18-
16 | const BAD32_3: f32 = 0.100_000_000_000_1;
18+
17 | const BAD32_3: f32 = 0.100_000_000_000_1;
1919
| ^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.1`
2020

2121
error: float has excessive precision
22-
--> $DIR/excessive_precision.rs:18:26
22+
--> $DIR/excessive_precision.rs:18:29
2323
|
24-
18 | const BAD64_1: f64 = 0.123_456_789_012_345_67f64;
25-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.12345678901234566`
24+
18 | const BAD32_EDGE: f32 = 1.000_000_9;
25+
| ^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.000_001`
2626

2727
error: float has excessive precision
28-
--> $DIR/excessive_precision.rs:19:26
28+
--> $DIR/excessive_precision.rs:20:26
2929
|
30-
19 | const BAD64_2: f64 = 0.123_456_789_012_345_67;
31-
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.12345678901234566`
30+
20 | const BAD64_1: f64 = 0.123_456_789_012_345_67f64;
31+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_012_345_66`
3232

3333
error: float has excessive precision
34-
--> $DIR/excessive_precision.rs:20:26
34+
--> $DIR/excessive_precision.rs:21:26
3535
|
36-
20 | const BAD64_3: f64 = 0.100_000_000_000_000_000_1;
36+
21 | const BAD64_2: f64 = 0.123_456_789_012_345_67;
37+
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_012_345_66`
38+
39+
error: float has excessive precision
40+
--> $DIR/excessive_precision.rs:22:26
41+
|
42+
22 | const BAD64_3: f64 = 0.100_000_000_000_000_000_1;
3743
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.1`
3844

3945
error: float has excessive precision
40-
--> $DIR/excessive_precision.rs:23:20
46+
--> $DIR/excessive_precision.rs:25:20
47+
|
48+
25 | println!("{}", 8.888_888_888_888_888_888_888);
49+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `8.888_888_888_888_89`
50+
51+
error: float has excessive precision
52+
--> $DIR/excessive_precision.rs:36:22
4153
|
42-
23 | println!("{}", 8.888_888_888_888_888_888_888);
43-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `8.88888888888889`
54+
36 | let bad32: f32 = 1.123_456_789;
55+
| ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8`
4456

4557
error: float has excessive precision
46-
--> $DIR/excessive_precision.rs:35:24
58+
--> $DIR/excessive_precision.rs:37:26
4759
|
48-
35 | let bad32_1: f32 = 1.123_456_789_f32;
49-
| ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.1234568`
60+
37 | let bad32_suf: f32 = 1.123_456_789_f32;
61+
| ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8`
5062

5163
error: float has excessive precision
52-
--> $DIR/excessive_precision.rs:36:24
64+
--> $DIR/excessive_precision.rs:38:21
5365
|
54-
36 | let bad32_2: f32 = 1.123_456_789;
55-
| ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.1234568`
66+
38 | let bad32_inf = 1.123_456_789_f32;
67+
| ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8`
5668

5769
error: float has excessive precision
58-
--> $DIR/excessive_precision.rs:38:24
70+
--> $DIR/excessive_precision.rs:40:22
5971
|
60-
38 | let bad64_1: f64 = 0.123_456_789_012_345_67f64;
61-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.12345678901234566`
72+
40 | let bad64: f64 = 0.123_456_789_012_345_67;
73+
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_012_345_66`
6274

6375
error: float has excessive precision
64-
--> $DIR/excessive_precision.rs:39:24
76+
--> $DIR/excessive_precision.rs:41:26
6577
|
66-
39 | let bad64_2: f64 = 0.123_456_789_012_345_67;
67-
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.12345678901234566`
78+
41 | let bad64_suf: f64 = 0.123_456_789_012_345_67f64;
79+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_012_345_66`
6880

6981
error: float has excessive precision
70-
--> $DIR/excessive_precision.rs:40:19
82+
--> $DIR/excessive_precision.rs:42:21
7183
|
72-
40 | let bad64_3 = 0.123_456_789_012_345_67;
73-
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.12345678901234566`
84+
42 | let bad64_inf = 0.123_456_789_012_345_67;
85+
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_012_345_66`
7486

7587
error: float has excessive precision
76-
--> $DIR/excessive_precision.rs:43:32
88+
--> $DIR/excessive_precision.rs:48:36
7789
|
78-
43 | let vec32: Vec<f32> = vec![0.123_456_789];
79-
| ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.12345679`
90+
48 | let bad_vec32: Vec<f32> = vec![0.123_456_789];
91+
| ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_79`
8092

8193
error: float has excessive precision
82-
--> $DIR/excessive_precision.rs:44:32
94+
--> $DIR/excessive_precision.rs:49:36
8395
|
84-
44 | let vec64: Vec<f64> = vec![0.123_456_789_123_456_789];
85-
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.12345678912345678`
96+
49 | let bad_vec64: Vec<f64> = vec![0.123_456_789_123_456_789];
97+
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_123_456_78`
8698

8799
error: float has excessive precision
88-
--> $DIR/excessive_precision.rs:48:24
100+
--> $DIR/excessive_precision.rs:53:24
89101
|
90-
48 | let bad_e32: f32 = 1.123_456_788_888e-10;
91-
| ^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.1234568e-10`
102+
53 | let bad_e32: f32 = 1.123_456_788_888e-10;
103+
| ^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8e-10`
92104

93105
error: float has excessive precision
94-
--> $DIR/excessive_precision.rs:51:27
106+
--> $DIR/excessive_precision.rs:56:27
95107
|
96-
51 | let bad_bige32: f32 = 1.123_456_788_888E-10;
97-
| ^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.1234568E-10`
108+
56 | let bad_bige32: f32 = 1.123_456_788_888E-10;
109+
| ^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8E-10`
98110

99-
error: aborting due to 16 previous errors
111+
error: aborting due to 18 previous errors
100112

0 commit comments

Comments
 (0)