Add subdiagnostic and suggestion for overflowing bin hex with sign bits
This commit is contained in:
parent
34d64ab7a2
commit
6033895ec2
3 changed files with 63 additions and 4 deletions
|
@ -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}`
|
.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}`
|
.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
|
.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
|
.help = consider using the type `{$suggestion_ty}` instead
|
||||||
|
|
||||||
lint_overflowing_int = literal out of range for `{$ty}`
|
lint_overflowing_int = literal out of range for `{$ty}`
|
||||||
|
|
|
@ -1342,6 +1342,8 @@ pub struct OverflowingBinHex<'a> {
|
||||||
pub sign: OverflowingBinHexSign,
|
pub sign: OverflowingBinHexSign,
|
||||||
#[subdiagnostic]
|
#[subdiagnostic]
|
||||||
pub sub: Option<OverflowingBinHexSub<'a>>,
|
pub sub: Option<OverflowingBinHexSub<'a>>,
|
||||||
|
#[subdiagnostic]
|
||||||
|
pub sign_bit_sub: Option<OverflowingBinHexSignBitSub<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum OverflowingBinHexSign {
|
pub enum OverflowingBinHexSign {
|
||||||
|
@ -1386,6 +1388,21 @@ pub enum OverflowingBinHexSub<'a> {
|
||||||
Help { suggestion_ty: &'a str },
|
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)]
|
#[derive(LintDiagnostic)]
|
||||||
#[diag(lint_overflowing_int)]
|
#[diag(lint_overflowing_int)]
|
||||||
#[note]
|
#[note]
|
||||||
|
|
|
@ -3,9 +3,10 @@ use crate::{
|
||||||
lints::{
|
lints::{
|
||||||
AtomicOrderingFence, AtomicOrderingLoad, AtomicOrderingStore, ImproperCTypes,
|
AtomicOrderingFence, AtomicOrderingLoad, AtomicOrderingStore, ImproperCTypes,
|
||||||
InvalidAtomicOrderingDiag, InvalidNanComparisons, InvalidNanComparisonsSuggestion,
|
InvalidAtomicOrderingDiag, InvalidNanComparisons, InvalidNanComparisonsSuggestion,
|
||||||
OnlyCastu8ToChar, OverflowingBinHex, OverflowingBinHexSign, OverflowingBinHexSub,
|
OnlyCastu8ToChar, OverflowingBinHex, OverflowingBinHexSign, OverflowingBinHexSignBitSub,
|
||||||
OverflowingInt, OverflowingIntHelp, OverflowingLiteral, OverflowingUInt,
|
OverflowingBinHexSub, OverflowingInt, OverflowingIntHelp, OverflowingLiteral,
|
||||||
RangeEndpointOutOfRange, UnusedComparisons, UseInclusiveRange, VariantSizeDifferencesDiag,
|
OverflowingUInt, RangeEndpointOutOfRange, UnusedComparisons, UseInclusiveRange,
|
||||||
|
VariantSizeDifferencesDiag,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use crate::{LateContext, LateLintPass, LintContext};
|
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(
|
cx.emit_spanned_lint(
|
||||||
OVERFLOWING_LITERALS,
|
OVERFLOWING_LITERALS,
|
||||||
expr.span,
|
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,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue