Skip to content

overflowing_literals lint behaves strangely with repeated negation #158295

Closed

Description

@theemathas

Code

#![allow(arithmetic_overflow)]

pub fn zero() {
    // lint
    let _ = 128_i8;
}

pub fn one() {
    // no lint
    let _ = -128_i8;
}

pub fn two() {
    // lint
    let _ = -(-128_i8);
}

pub fn three() {
    // no lint
    let _ = -(-(-128_i8));
}

Current output

error: literal out of range for `i8`
 --> src/lib.rs:5:13
  |
5 |     let _ = 128_i8;
  |             ^^^^^^
  |
  = note: the literal `128_i8` does not fit into the type `i8` whose range is `-128..=127`
  = help: consider using the type `u8` instead
  = note: `#[deny(overflowing_literals)]` on by default

error: literal out of range for `i8`
  --> src/lib.rs:15:16
   |
15 |     let _ = -(-128_i8);
   |                ^^^^^^
   |
   = note: the literal `128_i8` does not fit into the type `i8` whose range is `-128..=127`
   = help: consider using the type `u8` instead

Desired output

error: literal out of range for `i8`
 --> src/lib.rs:5:13
  |
5 |     let _ = 128_i8;
  |             ^^^^^^
  |
  = note: the literal `128_i8` does not fit into the type `i8` whose range is `-128..=127`
  = help: consider using the type `u8` instead
  = note: `#[deny(overflowing_literals)]` on by default

Rationale and extra context

The overflowing_literal lint is, I believe, supposed to consider the literal and not the surrounding context when deciding whether to lint. This is in contrast to the arithmetic_overflow lint, which only considers code that executes at run time, which excludes the negation inside a literal.

According to the reference, a negation in front of an integer does not result in an overflow. I think of this as: a negation, and only one negation, in front of an integer, is "part of" the integer. Therefore, the overflowing_literal lint should consider that when linting. It should not consider the second or third negation.

Therefore, I think that overflowing_literals should only lint on 128_i8 when there is no preceding negation at all. This is in contrast to the current behavior, which lints on 128_i8 preceded by an even number of negations.

Other cases

Rust Version

Reproducible on the playground with version 1.98.0-nightly (2026-06-22 4429659e4745016bd3f2)

Anything else?

No response

Activity

  1. self-assigned this
    on Jun 23, 2026
  2. added
    A-lintsArea: Lints (warnings about flaws in source code) such as unused_mut.
    A-diagnosticsArea: Messages for errors, warnings, and lints
    T-langRelevant to the language team
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    on Jun 23, 2026
  3. added a commit that references this issue on Jul 15, 2026
  4. added a commit that references this issue on Jul 15, 2026
  5. added a commit that references this issue on Jul 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

A-diagnosticsArea: Messages for errors, warnings, and lintsA-lintsArea: Lints (warnings about flaws in source code) such as unused_mut.L-overflowing_literalsLint: overflowing_literalsT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-langRelevant to the language team

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions