Error: attempt to multiply with overflow

Hi I am new to rust lang, i am running below code but getting error of overflow, if annotate type of value.

fn main() {
let x: u8 = 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 - 1;

    println!("{}", x);
}

can some one please help, because as per documentation it should value store from 0 - 255, if i dont annotate it will give me value, please HELP!

For the value to be u8, all operands of the expression need to be u8 as well. While the final value of this expression would fit into a u8, the expression 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 doesn't, which is why the compiler complains.

It works if you write it like this:

fn main() {
    let x: u8 = (2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 - 1) as u8;
    println!("{}", x);
}

This way the 2s and the 1 will be 64 or 32 bit integers and the final result is then converted into u8.

1 Like

Minor correction to @stefan-k final line; rust will always pick i32 when type of integer can't be inferred.

2 Likes

There’s also std::num::Wrapping when you need wrapping behavior at runtime.

1 Like

In other words, when directly assigning to a numerical variable of type T, the compiler will always infer that the type of every number in the expression of the assignment is of type T unless the numbers are within parenthesis. Eg,

let a: usize = 2 + 6 * 8 / 9;

is equivalent to

let a: usize = 2usize + 6usize * 8usize / 9usize;

And because not all operations are done in the same cpu cycle (Unless you manage to parallelize it), the result of every arithmetical operation must fit in the numerical type T

Hi, so in my case it was doing u8 * u8 * u8 * - i8? is my understanding correct? it should be all u8 unless we wrap them in ( ) ?

Hi Stefan-k, so basically are we doing conversion here using as keyword?

Hi @Jonh, you are saying when it can't infer what type of integer it is, it will pickup i32 by default and then it will convert to u8?

The use of parenthesis is for precedent ordering so the as takes effect on the expression rather than the single item before it.

To begin with integers start with a type {integer}. The left hand side of the as operator does not have anything to specify the concrete type so the compiler uses i32. The right is obviously what it wants turning into but is not used to for any inference on the left. (The compiler is also free to make optimised machine code so it is entirely possible calculations are done beforehand and the types differ in assembly.)

2 Likes