Skip to content

Commit c1664c5

Browse files
committed
Auto merge of rust-lang#6421 - xFrednet:4176-unreadable-literal-lint-fractal-option, r=Manishearth
Added a lint-fraction-readability flag to the configuration This adds an option to disable the `unreadable_literal` lint for floats with a longer fraction. This allows users to write `0.100200300` without getting a warning. Fixes rust-lang#4176 I have some open questions about this PR: 1. I've named the option `lint-fraction-readability` is this a good name or should I rename it to something else? 2. What should the default configuration value be? * The current default value is `true` as this was also the previous default. 3. Do I have to document this new option somewhere else or will it be extracted from the code comment? 4. The current fix option will also rewrite the fraction if the integer part violates the `unreadable_literal` lint it would otherwise also trigger the `inconsistent_digit_grouping` lint. Is this also okay? * `1.100200300` will be unaffected by the fix function * `100200300.100200300` will be effected and fixed to `100_200_300.100_200_300` --- The project needed some getting used to but I'm happy with the result. A big thank you to `@flip1995` for giving me some pointers for this implementation and to everyone for the great introduction documentation! --- changelog: Added the `unreadable-literal-lint-fractions` configuration to disable the `unreadable_literal` lint for fractions
2 parents 8d678bc + 898b7c5 commit c1664c5

File tree

10 files changed

+118
-37
lines changed

10 files changed

+118
-37
lines changed

clippy_lints/src/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1138,7 +1138,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
11381138
store.register_late_pass(|| box cargo_common_metadata::CargoCommonMetadata);
11391139
store.register_late_pass(|| box multiple_crate_versions::MultipleCrateVersions);
11401140
store.register_late_pass(|| box wildcard_dependencies::WildcardDependencies);
1141-
store.register_early_pass(|| box literal_representation::LiteralDigitGrouping);
1141+
let literal_representation_lint_fraction_readability = conf.unreadable_literal_lint_fractions;
1142+
store.register_early_pass(move || box literal_representation::LiteralDigitGrouping::new(literal_representation_lint_fraction_readability));
11421143
let literal_representation_threshold = conf.literal_representation_threshold;
11431144
store.register_early_pass(move || box literal_representation::DecimalLiteralRepresentation::new(literal_representation_threshold));
11441145
let enum_variant_name_threshold = conf.enum_variant_name_threshold;

clippy_lints/src/literal_representation.rs

+28-9
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use rustc_ast::ast::{Expr, ExprKind, Lit, LitKind};
1111
use rustc_errors::Applicability;
1212
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
1313
use rustc_middle::lint::in_external_macro;
14-
use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass};
14+
use rustc_session::{declare_tool_lint, impl_lint_pass};
1515

1616
declare_clippy_lint! {
1717
/// **What it does:** Warns if a long integral or floating-point constant does
@@ -32,7 +32,7 @@ declare_clippy_lint! {
3232
/// ```
3333
pub UNREADABLE_LITERAL,
3434
pedantic,
35-
"long integer literal without underscores"
35+
"long literal without underscores"
3636
}
3737

3838
declare_clippy_lint! {
@@ -208,7 +208,13 @@ impl WarningType {
208208
}
209209
}
210210

211-
declare_lint_pass!(LiteralDigitGrouping => [
211+
#[allow(clippy::module_name_repetitions)]
212+
#[derive(Copy, Clone)]
213+
pub struct LiteralDigitGrouping {
214+
lint_fraction_readability: bool,
215+
}
216+
217+
impl_lint_pass!(LiteralDigitGrouping => [
212218
UNREADABLE_LITERAL,
213219
INCONSISTENT_DIGIT_GROUPING,
214220
LARGE_DIGIT_GROUPS,
@@ -223,7 +229,7 @@ impl EarlyLintPass for LiteralDigitGrouping {
223229
}
224230

225231
if let ExprKind::Lit(ref lit) = expr.kind {
226-
Self::check_lit(cx, lit)
232+
self.check_lit(cx, lit)
227233
}
228234
}
229235
}
@@ -232,7 +238,13 @@ impl EarlyLintPass for LiteralDigitGrouping {
232238
const UUID_GROUP_LENS: [usize; 5] = [8, 4, 4, 4, 12];
233239

234240
impl LiteralDigitGrouping {
235-
fn check_lit(cx: &EarlyContext<'_>, lit: &Lit) {
241+
pub fn new(lint_fraction_readability: bool) -> Self {
242+
Self {
243+
lint_fraction_readability,
244+
}
245+
}
246+
247+
fn check_lit(self, cx: &EarlyContext<'_>, lit: &Lit) {
236248
if_chain! {
237249
if let Some(src) = snippet_opt(cx, lit.span);
238250
if let Some(mut num_lit) = NumericLiteral::from_lit(&src, &lit);
@@ -247,9 +259,12 @@ impl LiteralDigitGrouping {
247259

248260
let result = (|| {
249261

250-
let integral_group_size = Self::get_group_size(num_lit.integer.split('_'), num_lit.radix)?;
262+
let integral_group_size = Self::get_group_size(num_lit.integer.split('_'), num_lit.radix, true)?;
251263
if let Some(fraction) = num_lit.fraction {
252-
let fractional_group_size = Self::get_group_size(fraction.rsplit('_'), num_lit.radix)?;
264+
let fractional_group_size = Self::get_group_size(
265+
fraction.rsplit('_'),
266+
num_lit.radix,
267+
self.lint_fraction_readability)?;
253268

254269
let consistent = Self::parts_consistent(integral_group_size,
255270
fractional_group_size,
@@ -363,7 +378,11 @@ impl LiteralDigitGrouping {
363378

364379
/// Returns the size of the digit groups (or None if ungrouped) if successful,
365380
/// otherwise returns a `WarningType` for linting.
366-
fn get_group_size<'a>(groups: impl Iterator<Item = &'a str>, radix: Radix) -> Result<Option<usize>, WarningType> {
381+
fn get_group_size<'a>(
382+
groups: impl Iterator<Item = &'a str>,
383+
radix: Radix,
384+
lint_unreadable: bool,
385+
) -> Result<Option<usize>, WarningType> {
367386
let mut groups = groups.map(str::len);
368387

369388
let first = groups.next().expect("At least one group");
@@ -380,7 +399,7 @@ impl LiteralDigitGrouping {
380399
} else {
381400
Ok(Some(second))
382401
}
383-
} else if first > 5 {
402+
} else if first > 5 && lint_unreadable {
384403
Err(WarningType::UnreadableLiteral)
385404
} else {
386405
Ok(None)

clippy_lints/src/utils/conf.rs

+2
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,8 @@ define_Conf! {
170170
(warn_on_all_wildcard_imports, "warn_on_all_wildcard_imports": bool, false),
171171
/// Lint: DISALLOWED_METHOD. The list of blacklisted methods to lint about. NB: `bar` is not here since it has legitimate uses
172172
(disallowed_methods, "disallowed_methods": Vec<String>, Vec::<String>::new()),
173+
/// Lint: UNREADABLE_LITERAL. Should the fraction of a decimal be linted to include separators.
174+
(unreadable_literal_lint_fractions, "unreadable_literal_lint_fractions": bool, true),
173175
}
174176

175177
impl Default for Conf {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
unreadable-literal-lint-fractions = false
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#[deny(clippy::unreadable_literal)]
2+
3+
fn allow_inconsistent_digit_grouping() {
4+
#![allow(clippy::inconsistent_digit_grouping)]
5+
let _pass1 = 100_200_300.123456789;
6+
}
7+
8+
fn main() {
9+
allow_inconsistent_digit_grouping();
10+
11+
let _pass1 = 100_200_300.100_200_300;
12+
let _pass2 = 1.123456789;
13+
let _pass3 = 1.0;
14+
let _pass4 = 10000.00001;
15+
let _pass5 = 1.123456789e1;
16+
17+
// due to clippy::inconsistent-digit-grouping
18+
let _fail1 = 100_200_300.123456789;
19+
20+
// fail due to the integer part
21+
let _fail2 = 100200300.300200100;
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error: digits grouped inconsistently by underscores
2+
--> $DIR/test.rs:18:18
3+
|
4+
LL | let _fail1 = 100_200_300.123456789;
5+
| ^^^^^^^^^^^^^^^^^^^^^ help: consider: `100_200_300.123_456_789`
6+
|
7+
= note: `-D clippy::inconsistent-digit-grouping` implied by `-D warnings`
8+
9+
error: aborting due to previous error
10+
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown field `foobar`, expected one of `msrv`, `blacklisted-names`, `cognitive-complexity-threshold`, `cyclomatic-complexity-threshold`, `doc-valid-idents`, `too-many-arguments-threshold`, `type-complexity-threshold`, `single-char-binding-names-threshold`, `too-large-for-stack`, `enum-variant-name-threshold`, `enum-variant-size-threshold`, `verbose-bit-mask-threshold`, `literal-representation-threshold`, `trivial-copy-size-limit`, `pass-by-value-size-limit`, `too-many-lines-threshold`, `array-size-threshold`, `vec-box-size-threshold`, `max-trait-bounds`, `max-struct-bools`, `max-fn-params-bools`, `warn-on-all-wildcard-imports`, `disallowed-methods`, `third-party` at line 5 column 1
1+
error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown field `foobar`, expected one of `msrv`, `blacklisted-names`, `cognitive-complexity-threshold`, `cyclomatic-complexity-threshold`, `doc-valid-idents`, `too-many-arguments-threshold`, `type-complexity-threshold`, `single-char-binding-names-threshold`, `too-large-for-stack`, `enum-variant-name-threshold`, `enum-variant-size-threshold`, `verbose-bit-mask-threshold`, `literal-representation-threshold`, `trivial-copy-size-limit`, `pass-by-value-size-limit`, `too-many-lines-threshold`, `array-size-threshold`, `vec-box-size-threshold`, `max-trait-bounds`, `max-struct-bools`, `max-fn-params-bools`, `warn-on-all-wildcard-imports`, `disallowed-methods`, `unreadable-literal-lint-fractions`, `third-party` at line 5 column 1
22

33
error: aborting due to previous error
44

tests/ui/unreadable_literal.fixed

+14-4
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@ macro_rules! foo {
1010
};
1111
}
1212

13+
struct Bar(f32);
14+
15+
macro_rules! bar {
16+
() => {
17+
Bar(100200300400.100200300400500)
18+
};
19+
}
20+
1321
fn main() {
1422
let _good = (
1523
0b1011_i64,
@@ -26,10 +34,12 @@ fn main() {
2634
let _good_sci = 1.1234e1;
2735
let _bad_sci = 1.123_456e1;
2836

29-
let _fail9 = 0x00ab_cdef;
30-
let _fail10: u32 = 0xBAFE_BAFE;
31-
let _fail11 = 0x0abc_deff;
32-
let _fail12: i128 = 0x00ab_cabc_abca_bcab_cabc;
37+
let _fail1 = 0x00ab_cdef;
38+
let _fail2: u32 = 0xBAFE_BAFE;
39+
let _fail3 = 0x0abc_deff;
40+
let _fail4: i128 = 0x00ab_cabc_abca_bcab_cabc;
41+
let _fail5 = 1.100_300_400;
3342

3443
let _ = foo!();
44+
let _ = bar!();
3545
}

tests/ui/unreadable_literal.rs

+14-4
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@ macro_rules! foo {
1010
};
1111
}
1212

13+
struct Bar(f32);
14+
15+
macro_rules! bar {
16+
() => {
17+
Bar(100200300400.100200300400500)
18+
};
19+
}
20+
1321
fn main() {
1422
let _good = (
1523
0b1011_i64,
@@ -26,10 +34,12 @@ fn main() {
2634
let _good_sci = 1.1234e1;
2735
let _bad_sci = 1.123456e1;
2836

29-
let _fail9 = 0xabcdef;
30-
let _fail10: u32 = 0xBAFEBAFE;
31-
let _fail11 = 0xabcdeff;
32-
let _fail12: i128 = 0xabcabcabcabcabcabc;
37+
let _fail1 = 0xabcdef;
38+
let _fail2: u32 = 0xBAFEBAFE;
39+
let _fail3 = 0xabcdeff;
40+
let _fail4: i128 = 0xabcabcabcabcabcabc;
41+
let _fail5 = 1.100300400;
3342

3443
let _ = foo!();
44+
let _ = bar!();
3545
}

tests/ui/unreadable_literal.stderr

+24-18
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,72 @@
11
error: digits of hex or binary literal not grouped by four
2-
--> $DIR/unreadable_literal.rs:17:9
2+
--> $DIR/unreadable_literal.rs:25:9
33
|
44
LL | 0x1_234_567,
55
| ^^^^^^^^^^^ help: consider: `0x0123_4567`
66
|
77
= note: `-D clippy::unusual-byte-groupings` implied by `-D warnings`
88

99
error: long literal lacking separators
10-
--> $DIR/unreadable_literal.rs:25:17
10+
--> $DIR/unreadable_literal.rs:33:17
1111
|
1212
LL | let _bad = (0b110110_i64, 0xcafebabe_usize, 123456_f32, 1.234567_f32);
1313
| ^^^^^^^^^^^^ help: consider: `0b11_0110_i64`
1414
|
1515
= note: `-D clippy::unreadable-literal` implied by `-D warnings`
1616

1717
error: long literal lacking separators
18-
--> $DIR/unreadable_literal.rs:25:31
18+
--> $DIR/unreadable_literal.rs:33:31
1919
|
2020
LL | let _bad = (0b110110_i64, 0xcafebabe_usize, 123456_f32, 1.234567_f32);
2121
| ^^^^^^^^^^^^^^^^ help: consider: `0xcafe_babe_usize`
2222

2323
error: long literal lacking separators
24-
--> $DIR/unreadable_literal.rs:25:49
24+
--> $DIR/unreadable_literal.rs:33:49
2525
|
2626
LL | let _bad = (0b110110_i64, 0xcafebabe_usize, 123456_f32, 1.234567_f32);
2727
| ^^^^^^^^^^ help: consider: `123_456_f32`
2828

2929
error: long literal lacking separators
30-
--> $DIR/unreadable_literal.rs:25:61
30+
--> $DIR/unreadable_literal.rs:33:61
3131
|
3232
LL | let _bad = (0b110110_i64, 0xcafebabe_usize, 123456_f32, 1.234567_f32);
3333
| ^^^^^^^^^^^^ help: consider: `1.234_567_f32`
3434

3535
error: long literal lacking separators
36-
--> $DIR/unreadable_literal.rs:27:20
36+
--> $DIR/unreadable_literal.rs:35:20
3737
|
3838
LL | let _bad_sci = 1.123456e1;
3939
| ^^^^^^^^^^ help: consider: `1.123_456e1`
4040

4141
error: long literal lacking separators
42-
--> $DIR/unreadable_literal.rs:29:18
42+
--> $DIR/unreadable_literal.rs:37:18
4343
|
44-
LL | let _fail9 = 0xabcdef;
44+
LL | let _fail1 = 0xabcdef;
4545
| ^^^^^^^^ help: consider: `0x00ab_cdef`
4646

4747
error: long literal lacking separators
48-
--> $DIR/unreadable_literal.rs:30:24
48+
--> $DIR/unreadable_literal.rs:38:23
4949
|
50-
LL | let _fail10: u32 = 0xBAFEBAFE;
51-
| ^^^^^^^^^^ help: consider: `0xBAFE_BAFE`
50+
LL | let _fail2: u32 = 0xBAFEBAFE;
51+
| ^^^^^^^^^^ help: consider: `0xBAFE_BAFE`
5252

5353
error: long literal lacking separators
54-
--> $DIR/unreadable_literal.rs:31:19
54+
--> $DIR/unreadable_literal.rs:39:18
5555
|
56-
LL | let _fail11 = 0xabcdeff;
57-
| ^^^^^^^^^ help: consider: `0x0abc_deff`
56+
LL | let _fail3 = 0xabcdeff;
57+
| ^^^^^^^^^ help: consider: `0x0abc_deff`
5858

5959
error: long literal lacking separators
60-
--> $DIR/unreadable_literal.rs:32:25
60+
--> $DIR/unreadable_literal.rs:40:24
6161
|
62-
LL | let _fail12: i128 = 0xabcabcabcabcabcabc;
63-
| ^^^^^^^^^^^^^^^^^^^^ help: consider: `0x00ab_cabc_abca_bcab_cabc`
62+
LL | let _fail4: i128 = 0xabcabcabcabcabcabc;
63+
| ^^^^^^^^^^^^^^^^^^^^ help: consider: `0x00ab_cabc_abca_bcab_cabc`
6464

65-
error: aborting due to 10 previous errors
65+
error: long literal lacking separators
66+
--> $DIR/unreadable_literal.rs:41:18
67+
|
68+
LL | let _fail5 = 1.100300400;
69+
| ^^^^^^^^^^^ help: consider: `1.100_300_400`
70+
71+
error: aborting due to 11 previous errors
6672

0 commit comments

Comments
 (0)