Skip to content

Missing some warnings about "literal out of range for its type" #14165

Closed

Description

The places I'd expect to get warnings are indicated by the comments in this example:

fn main() {
    let a: u8 = 1000;
    let b = 1000u8;
    let c = 1000 as u8; // NO WARNING !!!

    let one: u8 = 1;
    let d = (one * 1000) as u32;
    let e = (one *   -1) as u32; // NO WARNING !!!
    let f = (one * -255) as u32; // NO WARNING !!!
    let g = (one * -256) as u32;

    println!("{}, {}, {}, {}, {}, {}, {}", a, b, c, d, e, f, g);
}

Here's the compiler output:

warning: literal out of range for its type, #[warn(type_overflow)] on by default
let a: u8 = 1000;
            ^~~~
warning: literal out of range for its type, #[warn(type_overflow)] on by default
let b = 1000u8;
        ^~~~~~
warning: literal out of range for its type, #[warn(type_overflow)] on by default
let d = (one * 1000) as u32;
               ^~~~
warning: literal out of range for its type, #[warn(type_overflow)] on by default
let g = (one * -256) as u32;
                ^~~

And here's the program output:
232, 232, 232, 232, 255, 1, 0

Activity

  1. lilyball commented on May 18, 2014

    @lilyball
    Contributor

    -1u8 produces an unsigned_negate warning, not a type_overflow warning. Consequently, (one * -1) is correct in not producing a type_overflow warning.

    This same logic applies to (one * -255) as well. 255 is in range for its type, so it doesn't get a type_overflow warning.

    It is arguable as to whether these cases should produce an unsigned_negate warning.

  2. lilyball commented on May 20, 2014

    @lilyball
    Contributor

    Saying ### as u8 should never produce a warning. That's an explicit cast, which means you're opting in to overflow behavior.

    Which is to say, -12u is likely to be unintentional, and the warning calls it out. -12 as uint is very much intentional. And in fact, if you get an unsigned_negate warning, the easiest way to fix it if it was intentional is to convert it to an as cast.

    Same thing with 1000 as u8. That right there is explicitly asking for the results of casting 1000 to a u8 type. The warning has a too-high probability of being a false positive.

  3. lilyball commented on May 21, 2014

    @lilyball
    Contributor

    let x: u8 = -1 feels more like an oversight to me, but I suspect it's actually a deliberate omission because it ends up being the exact same thing as 1u8 * -1. In both cases, the -1 is an unsuffixed integer literal, which is subsequently constraint to the u8 type.

    Of course, I can only speculate. I didn't implement the lint. But my feeling is that -1u8 is obviously weird and a lint on it is wholly unsurprising, but 1u8 * -1 is not so obviously weird, and flagging it with a lint may be more surprising (and have more false positives).

  4. hirschenberger commented on May 23, 2014

    @hirschenberger
    Contributor

    Hi, I wrote the lint for the unsigned negation and wanted to catch the obvious cases negating unsigned literals. A related issue to the case @tommit mentioned is #5477.
    The question is where we should draw the line between intentional and unintentional behaviour being helpful without annoying users?

  5. huonw commented on Jan 13, 2015

    @huonw
    Contributor

    Duplicate of #5477.

  6. added a commit that references this issue on Feb 20, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-lintsArea: Lints (warnings about flaws in source code) such as unused_mut.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions