rust-lang / rust-lang/rust-clippy

Warn about arithmetic before type cast/conversion

Open
#13,755 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-lint
Dominant language
Rust
Stars
13.5k
Forks
2.2k
Avg merge
2d 10h
Merged PRs (30d)
32

Description

What it does

It is easy mistake to do arithmetics before type conversion (or cast) instead of the other way around as probably intended.

E.g. when parsing data where length field is u16 and internally in Rust code we want to use usize.

fn main() {
    let value: u16 = std::hint::black_box(0xFFFF); // black box is to fool compiler in this example

    // this line is wrong and can lead to integer overflow:
    let sum: usize = usize::from(value + 2); // or: (value + 2) as usize

    println!("{sum}");
}

Link to playground

This code can lead to unexpected results since value + 2 is arithmetics on u16 instead of usize. It's also quite difficult to spot in code review.

The correct code should be:

    let sum: usize = usize::from(value) + 2;

This issue can be found with arithmetic_side_effects if enabled, but that lint is really noisy. I think this is special case of arithmetic side effects.

Advantage

The recommended code (type conversion before arithmetics) produces expected results while incorrect code (arithmetics before type conversion) can hide a bug for long time and cause difficult to debug bug in release builds.

And if overflow is really wanted then there is .overflowing_add() function for that already and making it really obvious.

Drawbacks

No response

Example
let parsed_value: u16 = parse_something();
let length: usize = usize::from(parsed_value + 2);

or

let parsed_value: u16 = parse_something();
let length: usize = (parsed_value + 2) as usize;

Could be written as:

let parsed_value: u16 = parse_something();
let length: usize = usize::from(parsed_value) + 2;

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reviewing the existing arithmetic_side_effects lint, which the issue identifies as related but too noisy. Use the Rust examples in the issue to define the conversion-before-arithmetic cases and determine how the proposed lint should distinguish intentional overflow. Done means an agreed lint scope and implementation with coverage for the shown u16 to usize patterns.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.