Skip to content

Commit 3e0e844

Browse files
committed
Add examples to clarify the casting rules
1 parent 6cf18ff commit 3e0e844

File tree

1 file changed

+75
-0
lines changed

1 file changed

+75
-0
lines changed

src/expressions/operator-expr.md

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,31 +358,106 @@ same trait object.
358358

359359
* Numeric cast
360360
* Casting between two integers of the same size (e.g. i32 -> u32) is a no-op
361+
```rust
362+
# #![allow(overflowing_literals)]
363+
assert_eq!(42i8 as u8, 42u8);
364+
assert_eq!(-1i8 as u8, 255u8);
365+
assert_eq!(255u8 as i8, -1i8);
366+
assert_eq!(0xffu8 as i8, 0xffi8);
367+
assert_eq!(-1i16 as u16, 65535u16);
368+
```
369+
361370
* Casting from a larger integer to a smaller integer (e.g. u32 -> u8) will
362371
truncate
372+
```rust
373+
# #![allow(overflowing_literals)]
374+
assert_eq!(42u16 as u8, 42u8);
375+
assert_eq!(1234u16 as u8, 210u8);
376+
assert_eq!(0xabcdu16 as u8, 0xcdu8);
377+
378+
assert_eq!(-42i16 as i8, -42i8);
379+
assert_eq!(1234u16 as i8, -46i8);
380+
assert_eq!(0xabcdi16 as i8, 0xcdi8);
381+
```
382+
363383
* Casting from a smaller integer to a larger integer (e.g. u8 -> u32) will
364384
* zero-extend if the source is unsigned
365385
* sign-extend if the source is signed
386+
```rust
387+
# #![allow(overflowing_literals)]
388+
assert_eq!(42i8 as i16, 42i16);
389+
assert_eq!(-17i8 as i16, -17i16);
390+
assert_eq!(0b1000_1010u8 as u16, 0b0000_0000_1000_1010u16, "Zero-extend");
391+
assert_eq!(0b0000_1010i8 as i16, 0b0000_0000_0000_1010i16, "Sign-extend 0");
392+
assert_eq!(0b1000_1010i8 as i16, 0b1111_1111_1000_1010i16, "Sign-extend 1");
393+
```
394+
366395
* Casting from a float to an integer will round the float towards zero
367396
* **[NOTE: currently this will cause Undefined Behavior if the rounded
368397
value cannot be represented by the target integer type][float-int]**.
369398
This includes Inf and NaN. This is a bug and will be fixed.
399+
```rust
400+
assert_eq!(42.9f32 as i32, 42);
401+
assert_eq!(-42.9f32 as i32, -42);
402+
assert_eq!(42_000_000f32 as i32, 42_000_000);
403+
println!("Undefined Behavior: {}", 1_000_000_000_000_000f32 as i32);
404+
println!("Undefined Behavior: {}", std::f32::NEG_INFINITY as i32);
405+
println!("Undefined Behavior: {}", std::f32::NAN as i32);
406+
```
407+
370408
* Casting from an integer to float will produce the closest possible float \*
371409
* if necessary, rounding is according to `roundTiesToEven` mode \*\*\*
372410
* on overflow, infinity (of the same sign as the input) is produced
373411
* note: with the current set of numeric types, overflow can only happen
374412
on `u128 as f32` for values greater or equal to `f32::MAX + (0.5 ULP)`
413+
```rust
414+
assert_eq!(1337i32 as f32, 1337f32);
415+
assert_eq!(123_456_789i32 as f32, 123_456_790f32, "Rounded");
416+
assert_eq!(0xffffffff_ffffffff_ffffffff_ffffffff_u128 as f32, std::f32::INFINITY);
417+
```
418+
375419
* Casting from an f32 to an f64 is perfect and lossless
420+
```rust
421+
assert_eq!(1_234.5f32 as f64, 1_234.5f64);
422+
assert_eq!(std::f32::INFINITY as f64, std::f64::INFINITY);
423+
assert!((std::f32::NAN as f64).is_nan());
424+
```
425+
376426
* Casting from an f64 to an f32 will produce the closest possible f32 \*\*
377427
* if necessary, rounding is according to `roundTiesToEven` mode \*\*\*
378428
* on overflow, infinity (of the same sign as the input) is produced
429+
```rust
430+
assert_eq!(1_234.5f64 as f32, 1_234.5f32);
431+
assert_eq!(1_234_567_891.123f64 as f32, 1_234_567_890f32, "Rounded");
432+
assert_eq!(std::f64::INFINITY as f32, std::f32::INFINITY);
433+
assert!((std::f64::NAN as f32).is_nan());
434+
```
435+
379436
* Enum cast
380437
* Casts an enum to its discriminant, then uses a numeric cast if needed.
438+
```rust
439+
enum Enum { A, B, C }
440+
assert_eq!(Enum::A as i32, 0);
441+
assert_eq!(Enum::B as i32, 1);
442+
assert_eq!(Enum::C as i32, 2);
443+
```
444+
381445
* Primitive to integer cast
382446
* `false` casts to `0`, `true` casts to `1`
383447
* `char` casts to the value of the code point, then uses a numeric cast if needed.
448+
```rust
449+
assert_eq!(false as i32, 0);
450+
assert_eq!(true as i32, 1);
451+
assert_eq!('A' as i32, 65);
452+
assert_eq!('Ö' as i32, 214);
453+
```
454+
384455
* `u8` to `char` cast
385456
* Casts to the `char` with the corresponding code point.
457+
```rust
458+
assert_eq!(65u8 as char, 'A');
459+
assert_eq!(214u8 as char, 'Ö');
460+
```
386461

387462
\* if integer-to-float casts with this rounding mode and overflow behavior are
388463
not supported natively by the hardware, these casts will likely be slower than

0 commit comments

Comments
 (0)