rust-lang / rust-by-example

Learn Rust with examples (Live code editor included)
https://doc.rust-lang.org/stable/rust-by-example/
Apache License 2.0
7k stars 1.34k forks source link

Casting example does not compile #1875

Closed zeritonius closed 1 month ago

zeritonius commented 1 month ago

I tried to run the example from this page: https://doc.rust-lang.org/stable/rust-by-example/types/cast.html but the example doesn't compile using the playground.

I received these errors, which I also attached as an image at the end of this message:

Compiling playground v0.0.1 (/playground)
error[E0308]: mismatched types
 --> src/main.rs:8:23
  |
8 |     let integer: u8 = decimal;
  |                  --   ^^^^^^^ expected `u8`, found `f32`
  |                  |
  |                  expected due to this

error[E0604]: only `u8` can be cast as `char`, not `f32`
  --> src/main.rs:17:21
   |
17 |     let character = decimal as char;
   |                     ^^^^^^^^^^^^^^^ invalid cast
   |
help: try `char::from_u32` instead (via a `u32`)
  --> src/main.rs:17:21
   |
17 |     let character = decimal as char;
   |                     ^^^^^^^^^^^^^^^

Some errors have detailed explanations: E0308, E0604.
For more information about an error, try `rustc --explain E0308`.
error: could not compile `playground` (bin "playground") due to 2 previous error

errors

marioidival commented 1 month ago

Hello @zeritonius did you tried to follow the comments instructions on page? I just follow and everythings works well...

Screenshot 2024-08-13 at 08 01 47

adarshswaminath commented 1 month ago

Hello @zeritonius , the issue you raised can be fixed by commenting out lines 8 and 17. You can find instructions to comment the lines directly in the code.

Here is the corrected code:

// Suppress all warnings from casts which overflow.
#![allow(overflowing_literals)]

fn main() {
    let decimal = 65.4321_f32;

    // Error! No implicit conversion
    // let integer: u8 = decimal;
    // FIXME ^ Comment out this line

    // Explicit conversion
    let integer = decimal as u8;
    let character = integer as char;

    // Error! There are limitations in conversion rules.
    // A float cannot be directly converted to a char.
    // let character = decimal as char;
    // FIXME ^ Comment out this line

    println!("Casting: {} -> {} -> {}", decimal, integer, character);

    // when casting any value to an unsigned type, T,
    // T::MAX + 1 is added or subtracted until the value
    // fits into the new type

    // 1000 already fits in a u16
    println!("1000 as a u16 is: {}", 1000 as u16);

    // 1000 - 256 - 256 - 256 = 232
    // Under the hood, the first 8 least significant bits (LSB) are kept,
    // while the rest towards the most significant bit (MSB) get truncated.
    println!("1000 as a u8 is : {}", 1000 as u8);
    // -1 + 256 = 255
    println!("  -1 as a u8 is : {}", (-1i8) as u8);

    // For positive numbers, this is the same as the modulus
    println!("1000 mod 256 is : {}", 1000 % 256);

    // When casting to a signed type, the (bitwise) result is the same as
    // first casting to the corresponding unsigned type. If the most significant
    // bit of that value is 1, then the value is negative.

    // Unless it already fits, of course.
    println!(" 128 as a i16 is: {}", 128 as i16);

    // In boundary case 128 value in 8-bit two's complement representation is -128
    println!(" 128 as a i8 is : {}", 128 as i8);

    // repeating the example above
    // 1000 as u8 -> 232
    println!("1000 as a u8 is : {}", 1000 as u8);
    // and the value of 232 in 8-bit two's complement representation is -24
    println!(" 232 as a i8 is : {}", 232 as i8);

    // Since Rust 1.45, the `as` keyword performs a *saturating cast*
    // when casting from float to int. If the floating point value exceeds
    // the upper bound or is less than the lower bound, the returned value
    // will be equal to the bound crossed.

    // 300.0 as u8 is 255
    println!(" 300.0 as u8 is : {}", 300.0_f32 as u8);
    // -100.0 as u8 is 0
    println!("-100.0 as u8 is : {}", -100.0_f32 as u8);
    // nan as u8 is 0
    println!("   nan as u8 is : {}", f32::NAN as u8);

    // This behavior incurs a small runtime cost and can be avoided
    // with unsafe methods, however the results might overflow and
    // return **unsound values**. Use these methods wisely:
    unsafe {
        // 300.0 as u8 is 44
        println!(" 300.0 as u8 is : {}", 300.0_f32.to_int_unchecked::<u8>());
        // -100.0 as u8 is 156
        println!("-100.0 as u8 is : {}", (-100.0_f32).to_int_unchecked::<u8>());
        // nan as u8 is 0
        println!("   nan as u8 is : {}", f32::NAN.to_int_unchecked::<u8>());
    }
}

And here is the output:

Casting: 65.4321 -> 65 -> A
1000 as a u16 is: 1000
1000 as a u8 is : 232
  -1 as a u8 is : 255
1000 mod 256 is : 232
 128 as a i16 is: 128
 128 as a i8 is : -128
1000 as a u8 is : 232
 232 as a i8 is : -24
 300.0 as u8 is : 255
-100.0 as u8 is : 0
   nan as u8 is : 0
 300.0 as u8 is : 44
-100.0 as u8 is : 156
   nan as u8 is : 0
zeritonius commented 1 month ago

Thank you so much for clarifying this!

My bad. I somewhat expected the code will run as it is, not that I will have to repair it myself. When the title is "Learn something by example" I expect the examples provided to work out of the box. If most of the examples work as they are, I expect all to work as they are. For the examples of the Rustlings repository, for instance, I expect them not to work, and to be my job to fix them.

I run first the program to see its output, then, if it works, I analyze the source code. I was wondering if it would be possible to add a warning in the error message, like "This does not compile by intention, so it's your job to fix it", to distinguish between intentional problems and genuine errors due to other factors.

Maybe I got too used to the Rust's panic behavior, and I panicked when the existing program didn't run when I clicked the play. :)

adarshswaminath commented 1 month ago

Thank you so much for clarifying this!

My bad. I somewhat expected the code will run as it is, not that I will have to repair it myself. When the title is "Learn something by example" I expect the examples provided to work out of the box. If most of the examples work as they are, I expect all to work as they are. For the examples of the Rustlings repository, for instance, I expect them not to work, and to be my job to fix them.

I run first the program to see its output, then, if it works, I analyze the source code. I was wondering if it would be possible to add a warning in the error message, like "This does not compile by intention, so it's your job to fix it", to distinguish between intentional problems and genuine errors due to other factors.

Maybe I got too used to the Rust's panic behavior, and I panicked when the existing program didn't run when I clicked the play. :)

No worries! Happy coding, and feel free to close the issue now. 😊

zeritonius commented 1 month ago

Thank you! I learned a new thing today - I didn't know I can close the issue myself - I thought that only someone with write access could do it.