Change:
<!-- Thank you for filing a bug report! Please provide a short summary of the bug, along with any information you feel relevant to replicating the bug. --I tried this code: I expected the code to compile since its i am assigning into x binary representation of i32::MIN, instead the compiler throws an error. <!-- If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. --: <!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summaryBacktrace</summary<p</p</details<!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
Similar issue happens with i16 as well where the below code dosen't compile
This looks intended to me. The binary literal , along with all other integer literals, represents the number in a more mathematical sense, instead of in a memory layout sense, so really means the integer , not (=)
A similar code compiles in c++ and hence I assumed it was a bug.
The C++ code works because C++ has implicit integer conversion. On a typical int = 32bit platform, means (in both rust and C++), and is typed in C++ (because it doesn't fit in . "The type of the integer literal is the first type in which the value can fit"), and then when you assign it back to int32_t, the result is {implementation-defined (C++17 or earlier)} / {reinterpreted in terms of 2's complement(C++20 or later)}, which gives you back i32::MIN. Its rust equivalent code should be
Ohh okay. Thanks for this information. Now I too feel that this behavior was intentional.
So it sounds like the problem here is that the diagnostic doesn't teach all this.
A nice diagnostic would be that, if an overflowing literal has "sign bit" set, guess the user wants to express a negative number in 2's complement, and suggest using the negative number literal
I can try and give this a shot. claim
Thus that very weird and probably a bad practice in most case. Doing binary operation on signed number is never a good thing in my book.
In that case, the compiler emits an error if you do it at compile-time since it's a case of the operation inducing wraparound (which lands on the same value). That's not a satisfying answer as to why the mere literal fails to compile.
Sorry, I haven't had the time to work on this. Releasing in hopes someone can pick it up. release-assignment
I'd like to give this a try, but I need some assistance as I have no experience working on the compiler. claim My idea is to add another and when the literal fits in the unsigned variant, but not the signed variant (in the provided example, and respectively) Facing a blocker now. How could one emit multiple suggestions (that share the same span) or "help"s? Would love to hear suggestions or guidance :)
Thank you all for closing this

Discussion:
.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 <ins> .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}` </ins> .help = consider using the type `{$suggestion_ty}` instead lint_overflowing_int = literal out of range for `{$ty}`

pub sign: OverflowingBinHexSign, #[subdiagnostic] pub sub: Option<OverflowingBinHexSub<'a>>, <ins> #[subdiagnostic] pub sign_bit_sub: Option<OverflowingBinHexSignBitSub<'a>>, </ins> } pub enum OverflowingBinHexSign {

Help { suggestion_ty: &'a str }, } <ins> #[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, } </ins> #[derive(LintDiagnostic)] #[diag(lint_overflowing_int)] #[note]

lints::{ AtomicOrderingFence, AtomicOrderingLoad, AtomicOrderingStore, ImproperCTypes, InvalidAtomicOrderingDiag, InvalidNanComparisons, InvalidNanComparisonsSuggestion, <del> OnlyCastu8ToChar, OverflowingBinHex, OverflowingBinHexSign, OverflowingBinHexSub, OverflowingInt, OverflowingIntHelp, OverflowingLiteral, OverflowingUInt, RangeEndpointOutOfRange, UnusedComparisons, UseInclusiveRange, VariantSizeDifferencesDiag, </del> <ins> OnlyCastu8ToChar, OverflowingBinHex, OverflowingBinHexSign, OverflowingBinHexSignBitSub, OverflowingBinHexSub, OverflowingInt, OverflowingIntHelp, OverflowingLiteral, OverflowingUInt, RangeEndpointOutOfRange, UnusedComparisons, UseInclusiveRange, VariantSizeDifferencesDiag, </ins> }, }; use crate::{LateContext, LateLintPass, LintContext};

} }, ); <ins> 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(); </ins> cx.emit_spanned_lint( OVERFLOWING_LITERALS, expr.span, <del> OverflowingBinHex { ty: t, lit: repr_str.clone(), dec: val, actually, sign, sub }, </del> <ins> OverflowingBinHex { ty: t, lit: repr_str.clone(), dec: val, actually, sign, sub, sign_bit_sub, }, </ins> ) }

--> $DIR/type-overflow.rs:10:16 | LL |     let fail = 0b1000_0001i8; <del> |                ^^^^^^^^^^^^^ help: consider using the type `u8` instead: `0b1000_0001u8` </del> <ins> |                ^^^^^^^^^^^^^ </ins> | = note: the literal `0b1000_0001i8` (decimal `129`) does not fit into the type `i8` and will become `-127i8` <ins> help: consider using the type `u8` instead | LL |     let fail = 0b1000_0001u8; |                ~~~~~~~~~~~~~ help: to use as a negative number (decimal `-127`), consider using the type `u8` for the literal and cast it to `i8` | LL |     let fail = 0b1000_0001u8 as i8; |                ~~~~~~~~~~~~~~~~~~~ </ins> warning: literal out of range for `i64` --> $DIR/type-overflow.rs:12:16 | LL |     let fail = 0x8000_0000_0000_0000i64; <del> |                ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using the type `u64` instead: `0x8000_0000_0000_0000u64` </del> <ins> |                ^^^^^^^^^^^^^^^^^^^^^^^^ </ins> | = note: the literal `0x8000_0000_0000_0000i64` (decimal `9223372036854775808`) does not fit into the type `i64` and will become `-9223372036854775808i64` <ins> help: consider using the type `u64` instead | LL |     let fail = 0x8000_0000_0000_0000u64; |                ~~~~~~~~~~~~~~~~~~~~~~~~ help: to use as a negative number (decimal `-9223372036854775808`), consider using the type `u64` for the literal and cast it to `i64` | LL |     let fail = 0x8000_0000_0000_0000u64 as i64; |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ </ins> warning: literal out of range for `u32` --> $DIR/type-overflow.rs:14:16

| = note: the literal `0x8000_0000_0000_0000_0000_0000_0000_0000` (decimal `170141183460469231731687303715884105728`) does not fit into the type `i128` and will become `-170141183460469231731687303715884105728i128` = help: consider using the type `u128` instead <ins> help: to use as a negative number (decimal `-170141183460469231731687303715884105728`), consider using the type `u128` for the literal and cast it to `i128` | LL |     let fail: i128 = 0x8000_0000_0000_0000_0000_0000_0000_0000u128 as i128; |                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ </ins> warning: literal out of range for `i32` --> $DIR/type-overflow.rs:19:16

| = note: the literal `0x8FFF_FFFF_FFFF_FFFE` (decimal `10376293541461622782`) does not fit into the type `i32` and will become `-2i32` = help: consider using the type `i128` instead <ins> help: to use as a negative number (decimal `-2`), consider using the type `u32` for the literal and cast it to `i32` | LL |     let fail = 0x8FFF_FFFF_FFFF_FFFEu32 as i32; |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ </ins> warning: literal out of range for `i8` --> $DIR/type-overflow.rs:21:17