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

Special case overflowing literal lints to warn about -iX::MIN #108383

Open
AaronKutch opened this issue Feb 23, 2023 · 4 comments
Open

Special case overflowing literal lints to warn about -iX::MIN #108383

AaronKutch opened this issue Feb 23, 2023 · 4 comments
Labels
A-lint Area: Lints (warnings about flaws in source code) such as unused_mut. C-enhancement Category: An issue proposing an enhancement or a PR with one. L-overflowing_literals Lint: overflowing_literals T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@AaronKutch
Copy link
Contributor

AaronKutch commented Feb 23, 2023

I just found several issues where people forget that -i32::MAX != i32::MIN, i32::MAX == 7fffffff while i32::MIN == -0x80000000. People see that -0x80000000 works and then mistakenly try to use +0x80000000 which doesn't work because i32 can't represent it. What we should actually do is detect when people try to type out 0x80000000i32 or 0x80i8, etc, and have a lint that warns about this problem. I'm thinking the lint should suggest casting to the unsigned type and back, because the user is probably trying to do bit manipulation which has subtleties with signed integers.

#53628, #99195, #108269

@Noratrieb Noratrieb added C-enhancement Category: An issue proposing an enhancement or a PR with one. A-lint Area: Lints (warnings about flaws in source code) such as unused_mut. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Feb 23, 2023
@gurry
Copy link
Contributor

gurry commented Sep 13, 2023

I'm thinking the lint should suggest casting to the unsigned type and back, because the user is probably trying to do bit manipulation which has subtleties with signed integers.

I think that is already roughly what the compiler suggests.

For example, this code:

#[allow(unused_variables)]
fn main() {
    let a = 5;
    let b = a ^ 0x80000000i32; 
}

results in the following diagnostic:

error: literal out of range for `i32`
 --> src/main.rs:4:17
  |
4 |     let b = a ^ 0x80000000i32; 
  |                 ^^^^^^^^^^^^^
  |
  = note: the literal `0x80000000i32` (decimal `2147483648`) does not fit into the type `i32` and will become `-2147483648i32`
  = note: `#[deny(overflowing_literals)]` on by default
help: consider using the type `u32` instead
  |
4 |     let b = a ^ 0x80000000u32; 
  |                 ~~~~~~~~~~~~~
help: to use as a negative number (decimal `-2147483648`), consider using the type `u32` for the literal and cast it to `i32`
  |
4 |     let b = a ^ 0x80000000u32 as i32; 
  |                 ~~~~~~~~~~~~~~~~~~~~

Maybe you want an additional note there about the pitfalls of using "edge" values like 0x80000000i32 because they are easily and often misconstrued as positive? Perhaps this note can also show an additional suggestion for -0x80000000i32 apart from the cast suggestion already shown.

@gurry
Copy link
Contributor

gurry commented Sep 13, 2023

I'm thinking the lint should suggest casting to the unsigned type and back, because the user is probably trying to do bit manipulation which has subtleties with signed integers.

I think that is already roughly what the compiler suggests.

The compiler didn't actually do that when the issue was filed. The help in question was added later in PR #111212.

So given that we have these suggestions now, would it make sense to close this issue?

@AaronKutch
Copy link
Contributor Author

AaronKutch commented Sep 13, 2023

The first new note solves half the issue cases I think. There are cases where people might not understand the asymmetry between MIN and MAX, it is not immediately obvious why removing an unary negative causes these errors unless you know about the edge case. I think one extra note should be added just for the iX::MIN case that says with hexadecimal, "note: iX::MIN == -0x80..., but iX::MAX == 0x7ff..., meaning that positive 0x80... is not representable as an iX." with the 'X' and '...' properly filled in.

@gurry
Copy link
Contributor

gurry commented Sep 14, 2023

Makes sense

@jieyouxu jieyouxu added the L-overflowing_literals Lint: overflowing_literals label May 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-lint Area: Lints (warnings about flaws in source code) such as unused_mut. C-enhancement Category: An issue proposing an enhancement or a PR with one. L-overflowing_literals Lint: overflowing_literals T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

4 participants