Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Assignment of hexadecimal and integer types is not interchangeable. #108269

Closed
TimePrinciple opened this issue Feb 20, 2023 · 8 comments
Closed
Labels
A-fmt Area: `std::fmt` A-lints Area: Lints (warnings about flaws in source code) such as unused_mut.

Comments

@TimePrinciple
Copy link

In code:

println!("{:#X}", i32::MIN);

It will tell me that i32::MIN is 0X80000000, but if I try to assign an i32 with 0X80000000, I would get an error says literal out of range.

I suggest to add methods to support assignment of integer types with exact bits, like I can assign i32 with the exact 32 bits in 0X80000000.

@ChrisDenton
Copy link
Member

ChrisDenton commented Feb 20, 2023

Currently the way to do this is

const VALUE: i32 = 0x80000000_u32 as i32;

@TimePrinciple
Copy link
Author

Currently the way to do this is

const VALUE: i32 = 0x80000000_u32 as i32;

I'm aware of that solution, but still, I can hard agree with the conversion. I mean, the binary representation of 0X80000000 is 0b1000 0000 0000 0000 no matter it is signed or unsigned. I want the integers can be assigned just as it is (assign each bit to the bits in side the integer type).

@ChrisDenton
Copy link
Member

For prior discussion see: #48073, #99195, #53628

@AaronKutch
Copy link
Contributor

AaronKutch commented Feb 23, 2023

No,

const VALUE: i32 = -0x80000000;

works just fine, I suspect the confusion is because -i32::MAX != i32::MIN. i32::MAX == 7fffffff and i32::MIN == -0x80000000.
The actual issue is that println!("{:x}"); prints with the unsigned value instead of the absolute value with -, but this is a design decision that can't be changed

@ChrisDenton
Copy link
Member

ChrisDenton commented Feb 23, 2023

That was brought up in an issue I linked earlier (#53628).

@TimePrinciple
Copy link
Author

No,

const VALUE: i32 = -0x80000000;

works just fine, I suspect the confusion is because -i32::MAX != i32::MIN. i32::MAX == 7fffffff and i32::MIN == -0x80000000. The actual issue is that println!("{:x}"); prints with the unsigned value instead of the absolute value with -, but this is a design decision that can't be changed

I totally agree if 0x8000 0000 is interpreted into a positive integer if the type of this literal is not specified explicitly, but 0x8000 0000_i32 should not work that way.

In my view, this is a matter of what context is chosen for interpretation here. In a signed integer, a 32-bit signed integer to be more specific, is in the context of two's complement representation, and the representation:

0x8000 0000

Expands to

1000 0000 0000 0000 0000 0000 0000 0000

In the context of 32-bit two's complement, the left-most bit is the sign bit denotes this number is negative, hence should be at least interpreted to a negative number. As of this particular value, which does not have its two's complement, the value of -2^31 is given to this representation.

My suggestion is we could have developed a method like i32::from_bit_pattern("10000000000000000000000000000000") or a string of hexadecimal or octal, to expand the value as it is, and put this pattern into the integer.

@AaronKutch
Copy link
Contributor

I disagree strongly, because then 256i8 won't mean the numerical value of what someone might think it does. I also do not want to special case things between hexadecimal (I think it was a mistake that Rust "{:x}" formats signed integers as unsigned in the first place, I didn't know that until now, also I personally use hexadecimal for numerical values anyway sometimes). It takes little code and zero cost to cast between signed and unsigned.

@scottmcm
Copy link
Member

we could have developed a method like

Well, the help suggests using u32, so you can put that in the literal and have 0x8000_0000_u32 as _ if you want.

I put some deeper thoughts about the lint itself in #99195 (comment)

@workingjubilee workingjubilee added A-fmt Area: `std::fmt` A-lints Area: Lints (warnings about flaws in source code) such as unused_mut. labels Feb 26, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-fmt Area: `std::fmt` A-lints Area: Lints (warnings about flaws in source code) such as unused_mut.
Projects
None yet
Development

No branches or pull requests

5 participants