From f2902494614643509685c3bf974287ac9844b2fd Mon Sep 17 00:00:00 2001 From: goth-turtle <93494392+goth-turtle@users.noreply.github.com> Date: Sat, 23 Apr 2022 22:20:50 +0200 Subject: [PATCH] mistyped_literal_suffixes: improve suggestions for integer types Instead of just always suggesting signed suffixes regardless of size of the value, it now suggests an unsigned suffix when the value wouldn't fit into the corresponding signed type, and ignores the literal entirely if it is too big for the unsigned type as well. --- clippy_lints/src/literal_representation.rs | 50 ++++++++++++++------ tests/ui/mistyped_literal_suffix.fixed | 12 ++++- tests/ui/mistyped_literal_suffix.rs | 12 ++++- tests/ui/mistyped_literal_suffix.stderr | 54 +++++++++++++++++----- 4 files changed, 101 insertions(+), 27 deletions(-) diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index b7430f49229..362d45991bb 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -42,17 +42,12 @@ /// This is most probably a typo /// /// ### Known problems - /// - Recommends a signed suffix, even though the number might be too big and an unsigned - /// suffix is required + /// - Does not match on integers too large to fit in the corresponding unsigned type /// - Does not match on `_127` since that is a valid grouping for decimal and octal numbers /// /// ### Example - /// ```rust - /// // Probably mistyped - /// 2_32; - /// - /// // Good - /// 2_i32; + /// `2_32` => `2_i32` + /// `250_8 => `250_u8` /// ``` #[clippy::version = "1.30.0"] pub MISTYPED_LITERAL_SUFFIXES, @@ -310,18 +305,47 @@ fn check_for_mistyped_suffix( return true; } - let (part, mistyped_suffixes, missing_char) = if let Some((_, exponent)) = &mut num_lit.exponent { - (exponent, &["32", "64"][..], 'f') + let (part, mistyped_suffixes, is_float) = if let Some((_, exponent)) = &mut num_lit.exponent { + (exponent, &["32", "64"][..], true) } else if num_lit.fraction.is_some() { - (&mut num_lit.integer, &["32", "64"][..], 'f') + (&mut num_lit.integer, &["32", "64"][..], true) } else { - (&mut num_lit.integer, &["8", "16", "32", "64"][..], 'i') + (&mut num_lit.integer, &["8", "16", "32", "64"][..], false) }; let mut split = part.rsplit('_'); let last_group = split.next().expect("At least one group"); if split.next().is_some() && mistyped_suffixes.contains(&last_group) { - *part = &part[..part.len() - last_group.len()]; + let main_part = &part[..part.len() - last_group.len()]; + let missing_char; + if is_float { + missing_char = 'f'; + } else { + let radix = match num_lit.radix { + Radix::Binary => 2, + Radix::Octal => 8, + Radix::Decimal => 10, + Radix::Hexadecimal => 16, + }; + if let Ok(int) = u64::from_str_radix(&main_part.replace('_', ""), radix) { + missing_char = match (last_group, int) { + ("8", i) if i8::try_from(i).is_ok() => 'i', + ("16", i) if i16::try_from(i).is_ok() => 'i', + ("32", i) if i32::try_from(i).is_ok() => 'i', + ("64", i) if i64::try_from(i).is_ok() => 'i', + ("8", u) if u8::try_from(u).is_ok() => 'u', + ("16", u) if u16::try_from(u).is_ok() => 'u', + ("32", u) if u32::try_from(u).is_ok() => 'u', + ("64", _) => 'u', + _ => { + return true; + }, + } + } else { + return true; + } + } + *part = main_part; let mut sugg = num_lit.format(); sugg.push('_'); sugg.push(missing_char); diff --git a/tests/ui/mistyped_literal_suffix.fixed b/tests/ui/mistyped_literal_suffix.fixed index 5d57638af43..a59384e0725 100644 --- a/tests/ui/mistyped_literal_suffix.fixed +++ b/tests/ui/mistyped_literal_suffix.fixed @@ -5,7 +5,8 @@ unused_variables, overflowing_literals, clippy::excessive_precision, - clippy::inconsistent_digit_grouping + clippy::inconsistent_digit_grouping, + clippy::unusual_byte_groupings )] fn main() { @@ -25,5 +26,14 @@ fn main() { let fail28 = 241_251_235E723_f64; let ok29 = 42279.911_32; + // testing that the suggestion actually fits in its type + let fail30 = 127_i8; // should be i8 + let fail31 = 240_u8; // should be u8 + let ok32 = 360_8; // doesnt fit in either, should be ignored + let fail33 = 0x1234_i16; + let fail34 = 0xABCD_u16; + let ok35 = 0x12345_16; + let fail36 = 0xFFFF_FFFF_FFFF_FFFF_u64; // u64 + let _ = 1.123_45E1_f32; } diff --git a/tests/ui/mistyped_literal_suffix.rs b/tests/ui/mistyped_literal_suffix.rs index 12171452885..01e425f9f1d 100644 --- a/tests/ui/mistyped_literal_suffix.rs +++ b/tests/ui/mistyped_literal_suffix.rs @@ -5,7 +5,8 @@ unused_variables, overflowing_literals, clippy::excessive_precision, - clippy::inconsistent_digit_grouping + clippy::inconsistent_digit_grouping, + clippy::unusual_byte_groupings )] fn main() { @@ -25,5 +26,14 @@ fn main() { let fail28 = 241251235E723_64; let ok29 = 42279.911_32; + // testing that the suggestion actually fits in its type + let fail30 = 127_8; // should be i8 + let fail31 = 240_8; // should be u8 + let ok32 = 360_8; // doesnt fit in either, should be ignored + let fail33 = 0x1234_16; + let fail34 = 0xABCD_16; + let ok35 = 0x12345_16; + let fail36 = 0xFFFF_FFFF_FFFF_FFFF_64; // u64 + let _ = 1.12345E1_32; } diff --git a/tests/ui/mistyped_literal_suffix.stderr b/tests/ui/mistyped_literal_suffix.stderr index d24543c26e4..6fcd1f2f180 100644 --- a/tests/ui/mistyped_literal_suffix.stderr +++ b/tests/ui/mistyped_literal_suffix.stderr @@ -1,5 +1,5 @@ error: mistyped literal suffix - --> $DIR/mistyped_literal_suffix.rs:12:18 + --> $DIR/mistyped_literal_suffix.rs:13:18 | LL | let fail14 = 2_32; | ^^^^ help: did you mean to write: `2_i32` @@ -7,64 +7,94 @@ LL | let fail14 = 2_32; = note: `#[deny(clippy::mistyped_literal_suffixes)]` on by default error: mistyped literal suffix - --> $DIR/mistyped_literal_suffix.rs:13:18 + --> $DIR/mistyped_literal_suffix.rs:14:18 | LL | let fail15 = 4_64; | ^^^^ help: did you mean to write: `4_i64` error: mistyped literal suffix - --> $DIR/mistyped_literal_suffix.rs:14:18 + --> $DIR/mistyped_literal_suffix.rs:15:18 | LL | let fail16 = 7_8; // | ^^^ help: did you mean to write: `7_i8` error: mistyped literal suffix - --> $DIR/mistyped_literal_suffix.rs:15:18 + --> $DIR/mistyped_literal_suffix.rs:16:18 | LL | let fail17 = 23_16; // | ^^^^^ help: did you mean to write: `23_i16` error: mistyped literal suffix - --> $DIR/mistyped_literal_suffix.rs:18:18 + --> $DIR/mistyped_literal_suffix.rs:19:18 | LL | let fail20 = 2__8; // | ^^^^ help: did you mean to write: `2_i8` error: mistyped literal suffix - --> $DIR/mistyped_literal_suffix.rs:19:18 + --> $DIR/mistyped_literal_suffix.rs:20:18 | LL | let fail21 = 4___16; // | ^^^^^^ help: did you mean to write: `4_i16` error: mistyped literal suffix - --> $DIR/mistyped_literal_suffix.rs:22:18 + --> $DIR/mistyped_literal_suffix.rs:23:18 | LL | let fail25 = 1E2_32; | ^^^^^^ help: did you mean to write: `1E2_f32` error: mistyped literal suffix - --> $DIR/mistyped_literal_suffix.rs:23:18 + --> $DIR/mistyped_literal_suffix.rs:24:18 | LL | let fail26 = 43E7_64; | ^^^^^^^ help: did you mean to write: `43E7_f64` error: mistyped literal suffix - --> $DIR/mistyped_literal_suffix.rs:24:18 + --> $DIR/mistyped_literal_suffix.rs:25:18 | LL | let fail27 = 243E17_32; | ^^^^^^^^^ help: did you mean to write: `243E17_f32` error: mistyped literal suffix - --> $DIR/mistyped_literal_suffix.rs:25:18 + --> $DIR/mistyped_literal_suffix.rs:26:18 | LL | let fail28 = 241251235E723_64; | ^^^^^^^^^^^^^^^^ help: did you mean to write: `241_251_235E723_f64` error: mistyped literal suffix - --> $DIR/mistyped_literal_suffix.rs:28:13 + --> $DIR/mistyped_literal_suffix.rs:30:18 + | +LL | let fail30 = 127_8; // should be i8 + | ^^^^^ help: did you mean to write: `127_i8` + +error: mistyped literal suffix + --> $DIR/mistyped_literal_suffix.rs:31:18 + | +LL | let fail31 = 240_8; // should be u8 + | ^^^^^ help: did you mean to write: `240_u8` + +error: mistyped literal suffix + --> $DIR/mistyped_literal_suffix.rs:33:18 + | +LL | let fail33 = 0x1234_16; + | ^^^^^^^^^ help: did you mean to write: `0x1234_i16` + +error: mistyped literal suffix + --> $DIR/mistyped_literal_suffix.rs:34:18 + | +LL | let fail34 = 0xABCD_16; + | ^^^^^^^^^ help: did you mean to write: `0xABCD_u16` + +error: mistyped literal suffix + --> $DIR/mistyped_literal_suffix.rs:36:18 + | +LL | let fail36 = 0xFFFF_FFFF_FFFF_FFFF_64; // u64 + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean to write: `0xFFFF_FFFF_FFFF_FFFF_u64` + +error: mistyped literal suffix + --> $DIR/mistyped_literal_suffix.rs:38:13 | LL | let _ = 1.12345E1_32; | ^^^^^^^^^^^^ help: did you mean to write: `1.123_45E1_f32` -error: aborting due to 11 previous errors +error: aborting due to 16 previous errors