Data types and its changes

I am newbie in Rust and before it didnt have much practice in other languages. Tell me please, why first code is compiled normally and return panic, and 2nd not compiled:
1st:

fn main() {
    println!("Hello, leg!");
    let numb: u8="200".parse().expect("Not a number!");
    {let numb = numb * numb;
    println!("{numb}");}
}

2nd:

fn main() {
    println!("Hello, leg!");
    let numb: u8=200;
    {let numb = numb * numb;
    println!("{numb}");}
}

The first one panics with the message:

thread 'main' panicked at 'attempt to multiply with overflow',

because 200 * 200 = 40000 which is too big a number to fit in the 8 bits of a u8.

The second fails to compile with the error:

attempt to compute `200_u8 * 200_u8`, which would overflow

For the same reason.

The difference is that in the second case 200 is a constant and the compiler can work out at compile time that 200 * 200 is too big. But in the first case the compiler has no idea what the output of parse is so the check cannot be done at compile time.

3 Likes

In a more technical sense of the meaning “compile successfully”, both code examples compile successfully.

The second code hits a so-called “deny by default” lint. Most useful lints in Rust are only warn-by-default, so you typically encounter them as warnings. A warning is not a compilation failure, but points out undesirable behavior in your code. Unlike “real” compilation failures, lints can try to be helpful by employing more vague / heuristic rules as to when they apply. The lint in question, called “arithmetic_overflow“ as pointed out by the error message

= note: `#[deny(arithmetic_overflow)]` on by default

is considered such a strong indicator that there’s undesirable behavior in your code, that the default way of displaying this lint is as an “error”, not a “warning”. This severity (aka “level”) can be modified by the user using the #[allow(…)] attribute to silence the lint entirely, or the #[warn(…)] attribute to turn it into a warning. Similarly, all lints, in particular also the ones usually being warnings, can be turned into “error”s using the #[deny(…)] attribute.

E.g. this way the code compiles with only a warning.

#![warn(arithmetic_overflow)]

fn main() {
    println!("Hello, leg!");
    let numb: u8=200;
    {let numb = numb * numb;
    println!("{numb}");}
}

Similarly, if you start with

fn main() {
    let x = 1;
}

which warns

warning: unused variable: `x`
 --> src/main.rs:2:9
  |
2 |     let x = 1;
  |         ^ help: if this is intentional, prefix it with an underscore: `_x`
  |
  = note: `#[warn(unused_variables)]` on by default

and then consequentially turn this lint into an error

#![deny(unused_variables)]
fn main() {
    let x = 1;
}

you get a comparable outcome to the default behavior of the arithmetic_overflow lint, i.e. an “error”.


These settings can also be influenced with compilation flags. Also, lints that are triggered in code in dependencies of your crate will never cause compilation failure[1]. This way, the compiler can introduce new deny-by-default lints without such a change being a breaking change, because – whilst it may break direct builds of your application (unless you’ve added compiler-flags not to fail due to lints) – it cannot break Rust libraries, which would be the most painful effect imaginable, and as indicated in the previous sentence, even old code of Rust applications can still be compiler without problems, as longs as you set the appropriate command line arguments.


  1. Relevant part:

    This feature is used heavily by Cargo; it will pass --cap-lints allow when compiling your dependencies, so that if they have any warnings, they do not pollute the output of your build.

    ↩︎
4 Likes

Thanks! So, the compiler does not check the invested transformations to more than 1 level?

Compiler cannot check the output of parse, since, as far as it is concerned, parse is an ordinary function with arbitrary behaviour.

2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.