Copy in some documentation about which casts are legal
This commit is contained in:
parent
bac2b13a5a
commit
f34e6ff084
@ -7,7 +7,7 @@ most dangerous features of Rust!
|
||||
|
||||
# `as`
|
||||
|
||||
The `as` keyword does basic casting:
|
||||
The `as` keyword does safe casting:
|
||||
|
||||
```rust
|
||||
let x: i32 = 5;
|
||||
@ -15,7 +15,63 @@ let x: i32 = 5;
|
||||
let y = x as i64;
|
||||
```
|
||||
|
||||
It only allows certain kinds of casting, however:
|
||||
There are three major categories of safe cast: explicit coercions, casts
|
||||
between numeric types, and pointer casts.
|
||||
|
||||
Casting is not transitive: even if `e as U1 as U2` is a valid
|
||||
expression, `e as U2` is not necessarily so (in fact it will only be valid if
|
||||
`U1` coerces to `U2`).
|
||||
|
||||
|
||||
## Explicit coercions
|
||||
|
||||
A cast `e as U` is valid if `e` has type `T` and `T` *coerces* to `U`.
|
||||
|
||||
For example:
|
||||
|
||||
```rust
|
||||
let a = "hello";
|
||||
let b = a as String
|
||||
```
|
||||
|
||||
Coercions always occur implicitly so this form is only for clarity.
|
||||
|
||||
## Numeric casts
|
||||
|
||||
A cast `e as U` is also valid in any of the following cases:
|
||||
|
||||
* `e` has type `T` and `T` and `U` are any numeric types; *numeric-cast*
|
||||
* `e` is a C-like enum and `U` is an integer type; *enum-cast*
|
||||
* `e` has type `bool` or `char` and `U` is an integer; *prim-int-cast*
|
||||
* `e` has type `u8` and `U` is `char`; *u8-char-cast*
|
||||
|
||||
For example
|
||||
|
||||
```rust
|
||||
let one = true as u8;
|
||||
let at_sign = 64 as char;
|
||||
```
|
||||
|
||||
## Pointer casts
|
||||
|
||||
Perhaps surprisingly, it is safe to cast pointers to and from integers, and
|
||||
to cast between pointers to different types subject to some constraints. It
|
||||
is only unsafe to dereference the pointer.
|
||||
|
||||
* `e` has type `*T`, `U` is a pointer to `*U_0`, and either `U_0: Sized` or
|
||||
unsize_kind(`T`) = unsize_kind(`U_0`); a *ptr-ptr-cast*
|
||||
* `e` has type `*T` and `U` is a numeric type, while `T: Sized`; *ptr-addr-cast*
|
||||
* `e` is an integer and `U` is `*U_0`, while `U_0: Sized`; *addr-ptr-cast*
|
||||
* `e` has type `&[T; n]` and `U` is `*const T`; *array-ptr-cast*
|
||||
* `e` is a function pointer type and `U` has type `*T`,
|
||||
while `T: Sized`; *fptr-ptr-cast*
|
||||
* `e` is a function pointer type and `U` is an integer; *fptr-addr-cast*
|
||||
|
||||
|
||||
# `transmute`
|
||||
|
||||
`as` only allows safe casting, and will for example reject an attempt to
|
||||
cast four bytes into a `u32`:
|
||||
|
||||
```rust,ignore
|
||||
let a = [0u8, 0u8, 0u8, 0u8];
|
||||
@ -31,13 +87,11 @@ let b = a as u32; // four eights makes 32
|
||||
^~~~~~~~
|
||||
```
|
||||
|
||||
It’s a ‘non-scalar cast’ because we have multiple values here: the four
|
||||
This is a ‘non-scalar cast’ because we have multiple values here: the four
|
||||
elements of the array. These kinds of casts are very dangerous, because they
|
||||
make assumptions about the way that multiple underlying structures are
|
||||
implemented. For this, we need something more dangerous.
|
||||
|
||||
# `transmute`
|
||||
|
||||
The `transmute` function is provided by a [compiler intrinsic][intrinsics], and
|
||||
what it does is very simple, but very scary. It tells Rust to treat a value of
|
||||
one type as though it were another type. It does this regardless of the
|
||||
|
Loading…
x
Reference in New Issue
Block a user