Skip to content

Commit e5d0d53

Browse files
emilkehuss
authored andcommitted
Add examples to clarify the casting rules
1 parent 5110ba4 commit e5d0d53

File tree

1 file changed

+82
-0
lines changed

1 file changed

+82
-0
lines changed

src/expressions/operator-expr.md

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,25 +398,88 @@ reference types and `mut` or `const` in pointer types.
398398

399399
* Casting between two integers of the same size (e.g. i32 -> u32) is a no-op
400400
(Rust uses 2's complement for negative values of fixed integers)
401+
402+
```rust
403+
# #![allow(overflowing_literals)]
404+
assert_eq!(42i8 as u8, 42u8);
405+
assert_eq!(-1i8 as u8, 255u8);
406+
assert_eq!(255u8 as i8, -1i8);
407+
assert_eq!(0xffu8 as i8, 0xffi8);
408+
assert_eq!(-1i16 as u16, 65535u16);
409+
```
410+
401411
* Casting from a larger integer to a smaller integer (e.g. u32 -> u8) will
402412
truncate
413+
414+
```rust
415+
# #![allow(overflowing_literals)]
416+
assert_eq!(42u16 as u8, 42u8);
417+
assert_eq!(1234u16 as u8, 210u8);
418+
assert_eq!(0xabcdu16 as u8, 0xcdu8);
419+
420+
assert_eq!(-42i16 as i8, -42i8);
421+
assert_eq!(1234u16 as i8, -46i8);
422+
assert_eq!(0xabcdi16 as i8, 0xcdi8);
423+
```
424+
403425
* Casting from a smaller integer to a larger integer (e.g. u8 -> u32) will
404426
* zero-extend if the source is unsigned
405427
* sign-extend if the source is signed
428+
429+
```rust
430+
# #![allow(overflowing_literals)]
431+
assert_eq!(42i8 as i16, 42i16);
432+
assert_eq!(-17i8 as i16, -17i16);
433+
assert_eq!(0b1000_1010u8 as u16, 0b0000_0000_1000_1010u16, "Zero-extend");
434+
assert_eq!(0b0000_1010i8 as i16, 0b0000_0000_0000_1010i16, "Sign-extend 0");
435+
assert_eq!(0b1000_1010i8 as i16, 0b1111_1111_1000_1010i16, "Sign-extend 1");
436+
```
437+
406438
* Casting from a float to an integer will round the float towards zero
407439
* `NaN` will return `0`
408440
* Values larger than the maximum integer value, including `INFINITY`, will saturate to the maximum value of the integer type.
409441
* Values smaller than the minimum integer value, including `NEG_INFINITY`, will saturate to the minimum value of the integer type.
442+
443+
```rust
444+
assert_eq!(42.9f32 as i32, 42);
445+
assert_eq!(-42.9f32 as i32, -42);
446+
assert_eq!(42_000_000f32 as i32, 42_000_000);
447+
println!("Undefined Behavior: {}", 1_000_000_000_000_000f32 as i32);
448+
println!("Undefined Behavior: {}", std::f32::NEG_INFINITY as i32);
449+
println!("Undefined Behavior: {}", std::f32::NAN as i32);
450+
```
451+
410452
* Casting from an integer to float will produce the closest possible float \*
411453
* if necessary, rounding is according to `roundTiesToEven` mode \*\*\*
412454
* on overflow, infinity (of the same sign as the input) is produced
413455
* note: with the current set of numeric types, overflow can only happen
414456
on `u128 as f32` for values greater or equal to `f32::MAX + (0.5 ULP)`
457+
458+
```rust
459+
assert_eq!(1337i32 as f32, 1337f32);
460+
assert_eq!(123_456_789i32 as f32, 123_456_790f32, "Rounded");
461+
assert_eq!(0xffffffff_ffffffff_ffffffff_ffffffff_u128 as f32, std::f32::INFINITY);
462+
```
463+
415464
* Casting from an f32 to an f64 is perfect and lossless
465+
466+
```rust
467+
assert_eq!(1_234.5f32 as f64, 1_234.5f64);
468+
assert_eq!(std::f32::INFINITY as f64, std::f64::INFINITY);
469+
assert!((std::f32::NAN as f64).is_nan());
470+
```
471+
416472
* Casting from an f64 to an f32 will produce the closest possible f32 \*\*
417473
* if necessary, rounding is according to `roundTiesToEven` mode \*\*\*
418474
* on overflow, infinity (of the same sign as the input) is produced
419475

476+
```rust
477+
assert_eq!(1_234.5f64 as f32, 1_234.5f32);
478+
assert_eq!(1_234_567_891.123f64 as f32, 1_234_567_890f32, "Rounded");
479+
assert_eq!(std::f64::INFINITY as f32, std::f32::INFINITY);
480+
assert!((std::f64::NAN as f32).is_nan());
481+
```
482+
420483
\* if integer-to-float casts with this rounding mode and overflow behavior are
421484
not supported natively by the hardware, these casts will likely be slower than
422485
expected.
@@ -437,15 +500,34 @@ Casting is limited to the following kinds of enumerations:
437500
* [Unit-only enums]
438501
* [Field-less enums] without [explicit discriminants], or where only unit-variants have explicit discriminants
439502

503+
```rust
504+
enum Enum { A, B, C }
505+
assert_eq!(Enum::A as i32, 0);
506+
assert_eq!(Enum::B as i32, 1);
507+
assert_eq!(Enum::C as i32, 2);
508+
```
509+
440510
#### Primitive to integer cast
441511

442512
* `false` casts to `0`, `true` casts to `1`
443513
* `char` casts to the value of the code point, then uses a numeric cast if needed.
444514

515+
```rust
516+
assert_eq!(false as i32, 0);
517+
assert_eq!(true as i32, 1);
518+
assert_eq!('A' as i32, 65);
519+
assert_eq!('Ö' as i32, 214);
520+
```
521+
445522
#### `u8` to `char` cast
446523

447524
Casts to the `char` with the corresponding code point.
448525

526+
```rust
527+
assert_eq!(65u8 as char, 'A');
528+
assert_eq!(214u8 as char, 'Ö');
529+
```
530+
449531
#### Pointer to address cast
450532

451533
Casting from a raw pointer to an integer produces the machine address of the referenced memory.

0 commit comments

Comments
 (0)