diff options
| author | Nicky Lim <nickylim.p@gmail.com> | 2023-05-05 00:29:11 +0700 |
|---|---|---|
| committer | Nicky Lim <nickylim.p@gmail.com> | 2023-06-11 18:27:26 +0800 |
| commit | 6033895ec20bc6def7eee32eb3532faa8b1c67d5 (patch) | |
| tree | b94492ca44c1976d8811e39efb207b39c456a2f5 | |
| parent | 34d64ab7a21f704adb496ee2749242fc3511f0f8 (diff) | |
| download | rust-6033895ec20bc6def7eee32eb3532faa8b1c67d5.tar.gz rust-6033895ec20bc6def7eee32eb3532faa8b1c67d5.zip | |
Add subdiagnostic and suggestion for overflowing bin hex with sign bits
| -rw-r--r-- | compiler/rustc_lint/messages.ftl | 1 | ||||
| -rw-r--r-- | compiler/rustc_lint/src/lints.rs | 17 | ||||
| -rw-r--r-- | compiler/rustc_lint/src/types.rs | 49 |
3 files changed, 63 insertions, 4 deletions
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 5e13ee7b8a4..c66fcdec716 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -425,6 +425,7 @@ lint_overflowing_bin_hex = literal out of range for `{$ty}` .negative_becomes_note = and the value `-{$lit}` will become `{$actually}{$ty}` .positive_note = the literal `{$lit}` (decimal `{$dec}`) does not fit into the type `{$ty}` and will become `{$actually}{$ty}` .suggestion = consider using the type `{$suggestion_ty}` instead + .sign_bit_suggestion = to use as a negative number (decimal `{$negative_val}`), consider using the type `{$uint_ty}` for the literal and cast it to `{$int_ty}` .help = consider using the type `{$suggestion_ty}` instead lint_overflowing_int = literal out of range for `{$ty}` diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index e990c771bdf..89fa5713b73 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1342,6 +1342,8 @@ pub struct OverflowingBinHex<'a> { pub sign: OverflowingBinHexSign, #[subdiagnostic] pub sub: Option<OverflowingBinHexSub<'a>>, + #[subdiagnostic] + pub sign_bit_sub: Option<OverflowingBinHexSignBitSub<'a>>, } pub enum OverflowingBinHexSign { @@ -1386,6 +1388,21 @@ pub enum OverflowingBinHexSub<'a> { Help { suggestion_ty: &'a str }, } +#[derive(Subdiagnostic)] +#[suggestion( + lint_sign_bit_suggestion, + code = "{lit_no_suffix}{uint_ty} as {int_ty}", + applicability = "maybe-incorrect" +)] +pub struct OverflowingBinHexSignBitSub<'a> { + #[primary_span] + pub span: Span, + pub lit_no_suffix: &'a str, + pub negative_val: String, + pub uint_ty: &'a str, + pub int_ty: &'a str, +} + #[derive(LintDiagnostic)] #[diag(lint_overflowing_int)] #[note] diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 264a59c5585..ec9e7c7fdae 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -3,9 +3,10 @@ use crate::{ lints::{ AtomicOrderingFence, AtomicOrderingLoad, AtomicOrderingStore, ImproperCTypes, InvalidAtomicOrderingDiag, InvalidNanComparisons, InvalidNanComparisonsSuggestion, - OnlyCastu8ToChar, OverflowingBinHex, OverflowingBinHexSign, OverflowingBinHexSub, - OverflowingInt, OverflowingIntHelp, OverflowingLiteral, OverflowingUInt, - RangeEndpointOutOfRange, UnusedComparisons, UseInclusiveRange, VariantSizeDifferencesDiag, + OnlyCastu8ToChar, OverflowingBinHex, OverflowingBinHexSign, OverflowingBinHexSignBitSub, + OverflowingBinHexSub, OverflowingInt, OverflowingIntHelp, OverflowingLiteral, + OverflowingUInt, RangeEndpointOutOfRange, UnusedComparisons, UseInclusiveRange, + VariantSizeDifferencesDiag, }, }; use crate::{LateContext, LateLintPass, LintContext}; @@ -297,10 +298,50 @@ fn report_bin_hex_error( } }, ); + let sign_bit_sub = (!negative) + .then(|| { + let ty::Int(int_ty) = cx.typeck_results().node_type(expr.hir_id).kind() else { + return None; + }; + + let Some(bit_width) = int_ty.bit_width() else { + return None; // isize case + }; + + // Skip if sign bit is not set + if (val & (1 << (bit_width - 1))) == 0 { + return None; + } + + let lit_no_suffix = + if let Some(pos) = repr_str.chars().position(|c| c == 'i' || c == 'u') { + repr_str.split_at(pos).0 + } else { + &repr_str + }; + + Some(OverflowingBinHexSignBitSub { + span: expr.span, + lit_no_suffix, + negative_val: actually.clone(), + int_ty: int_ty.name_str(), + uint_ty: int_ty.to_unsigned().name_str(), + }) + }) + .flatten(); + cx.emit_spanned_lint( OVERFLOWING_LITERALS, expr.span, - OverflowingBinHex { ty: t, lit: repr_str.clone(), dec: val, actually, sign, sub }, + OverflowingBinHex { + ty: t, + lit: repr_str.clone(), + dec: val, + actually, + sign, + sub, + sign_bit_sub, + }, ) } |
