Skip to content

Commit 59d3bb2

Browse files
authored
Merge pull request #686 from emilk/add-cast-examples
Add examples to clarify the casting rules
2 parents 5110ba4 + bb6f41b commit 59d3bb2

File tree

1 file changed

+78
-0
lines changed

1 file changed

+78
-0
lines changed

src/expressions/operator-expr.md

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,25 +398,84 @@ 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+
assert_eq!(42i8 as u8, 42u8);
404+
assert_eq!(-1i8 as u8, 255u8);
405+
assert_eq!(255u8 as i8, -1i8);
406+
assert_eq!(-1i16 as u16, 65535u16);
407+
```
408+
401409
* Casting from a larger integer to a smaller integer (e.g. u32 -> u8) will
402410
truncate
411+
412+
```rust
413+
assert_eq!(42u16 as u8, 42u8);
414+
assert_eq!(1234u16 as u8, 210u8);
415+
assert_eq!(0xabcdu16 as u8, 0xcdu8);
416+
417+
assert_eq!(-42i16 as i8, -42i8);
418+
assert_eq!(1234u16 as i8, -46i8);
419+
assert_eq!(0xabcdi32 as i8, -51i8);
420+
```
421+
403422
* Casting from a smaller integer to a larger integer (e.g. u8 -> u32) will
404423
* zero-extend if the source is unsigned
405424
* sign-extend if the source is signed
425+
426+
```rust
427+
assert_eq!(42i8 as i16, 42i16);
428+
assert_eq!(-17i8 as i16, -17i16);
429+
assert_eq!(0b1000_1010u8 as u16, 0b0000_0000_1000_1010u16, "Zero-extend");
430+
assert_eq!(0b0000_1010i8 as i16, 0b0000_0000_0000_1010i16, "Sign-extend 0");
431+
assert_eq!(0b1000_1010u8 as i8 as i16, 0b1111_1111_1000_1010u16 as i16, "Sign-extend 1");
432+
```
433+
406434
* Casting from a float to an integer will round the float towards zero
407435
* `NaN` will return `0`
408436
* Values larger than the maximum integer value, including `INFINITY`, will saturate to the maximum value of the integer type.
409437
* Values smaller than the minimum integer value, including `NEG_INFINITY`, will saturate to the minimum value of the integer type.
438+
439+
```rust
440+
assert_eq!(42.9f32 as i32, 42);
441+
assert_eq!(-42.9f32 as i32, -42);
442+
assert_eq!(42_000_000f32 as i32, 42_000_000);
443+
assert_eq!(std::f32::NAN as i32, 0);
444+
assert_eq!(1_000_000_000_000_000f32 as i32, 0x7fffffffi32);
445+
assert_eq!(std::f32::NEG_INFINITY as i32, -0x80000000i32);
446+
```
447+
410448
* Casting from an integer to float will produce the closest possible float \*
411449
* if necessary, rounding is according to `roundTiesToEven` mode \*\*\*
412450
* on overflow, infinity (of the same sign as the input) is produced
413451
* note: with the current set of numeric types, overflow can only happen
414452
on `u128 as f32` for values greater or equal to `f32::MAX + (0.5 ULP)`
453+
454+
```rust
455+
assert_eq!(1337i32 as f32, 1337f32);
456+
assert_eq!(123_456_789i32 as f32, 123_456_790f32, "Rounded");
457+
assert_eq!(0xffffffff_ffffffff_ffffffff_ffffffff_u128 as f32, std::f32::INFINITY);
458+
```
459+
415460
* Casting from an f32 to an f64 is perfect and lossless
461+
462+
```rust
463+
assert_eq!(1_234.5f32 as f64, 1_234.5f64);
464+
assert_eq!(std::f32::INFINITY as f64, std::f64::INFINITY);
465+
assert!((std::f32::NAN as f64).is_nan());
466+
```
467+
416468
* Casting from an f64 to an f32 will produce the closest possible f32 \*\*
417469
* if necessary, rounding is according to `roundTiesToEven` mode \*\*\*
418470
* on overflow, infinity (of the same sign as the input) is produced
419471

472+
```rust
473+
assert_eq!(1_234.5f64 as f32, 1_234.5f32);
474+
assert_eq!(1_234_567_891.123f64 as f32, 1_234_567_890f32, "Rounded");
475+
assert_eq!(std::f64::INFINITY as f32, std::f32::INFINITY);
476+
assert!((std::f64::NAN as f32).is_nan());
477+
```
478+
420479
\* if integer-to-float casts with this rounding mode and overflow behavior are
421480
not supported natively by the hardware, these casts will likely be slower than
422481
expected.
@@ -437,15 +496,34 @@ Casting is limited to the following kinds of enumerations:
437496
* [Unit-only enums]
438497
* [Field-less enums] without [explicit discriminants], or where only unit-variants have explicit discriminants
439498

499+
```rust
500+
enum Enum { A, B, C }
501+
assert_eq!(Enum::A as i32, 0);
502+
assert_eq!(Enum::B as i32, 1);
503+
assert_eq!(Enum::C as i32, 2);
504+
```
505+
440506
#### Primitive to integer cast
441507

442508
* `false` casts to `0`, `true` casts to `1`
443509
* `char` casts to the value of the code point, then uses a numeric cast if needed.
444510

511+
```rust
512+
assert_eq!(false as i32, 0);
513+
assert_eq!(true as i32, 1);
514+
assert_eq!('A' as i32, 65);
515+
assert_eq!('Ö' as i32, 214);
516+
```
517+
445518
#### `u8` to `char` cast
446519

447520
Casts to the `char` with the corresponding code point.
448521

522+
```rust
523+
assert_eq!(65u8 as char, 'A');
524+
assert_eq!(214u8 as char, 'Ö');
525+
```
526+
449527
#### Pointer to address cast
450528

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

0 commit comments

Comments
 (0)