|
|
@ -1,9 +1,21 @@
|
|
|
|
% Casts
|
|
|
|
% Casts
|
|
|
|
|
|
|
|
|
|
|
|
Casts are a superset of coercions: every coercion can be explicitly invoked via
|
|
|
|
Casts are a superset of coercions: every coercion can be explicitly
|
|
|
|
a cast, but some conversions *require* a cast. These "true casts" are generally
|
|
|
|
invoked via a cast. However some conversions *require* a cast.
|
|
|
|
regarded as dangerous or problematic actions. True casts revolve around raw
|
|
|
|
While coercions are pervasive and largely harmless, these "true casts"
|
|
|
|
pointers and the primitive numeric types. True casts aren't checked.
|
|
|
|
are rare and potentially dangerous. As such, casts must be explicitly invoked
|
|
|
|
|
|
|
|
using the `as` keyword: `expr as Type`.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
True casts generally revolve around raw pointers and the primitive numeric
|
|
|
|
|
|
|
|
types. Even though they're dangerous, these casts are *infallible* at runtime.
|
|
|
|
|
|
|
|
If a cast triggers some subtle corner case no indication will be given that
|
|
|
|
|
|
|
|
this occurred. The cast will simply succeed.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
That said, casts aren't `unsafe` because they generally can't violate memory
|
|
|
|
|
|
|
|
safety *on their own*. For instance, converting an integer to a raw pointer can
|
|
|
|
|
|
|
|
very easily lead to terrible things. However the act of creating the pointer
|
|
|
|
|
|
|
|
itself is safe, because actually using a raw pointer is already marked as
|
|
|
|
|
|
|
|
`unsafe`.
|
|
|
|
|
|
|
|
|
|
|
|
Here's an exhaustive list of all the true casts. For brevity, we will use `*`
|
|
|
|
Here's an exhaustive list of all the true casts. For brevity, we will use `*`
|
|
|
|
to denote either a `*const` or `*mut`, and `integer` to denote any integral
|
|
|
|
to denote either a `*const` or `*mut`, and `integer` to denote any integral
|
|
|
@ -22,13 +34,8 @@ primitive:
|
|
|
|
* `fn as *T` where `T: Sized`
|
|
|
|
* `fn as *T` where `T: Sized`
|
|
|
|
* `fn as integer`
|
|
|
|
* `fn as integer`
|
|
|
|
|
|
|
|
|
|
|
|
where `&.T` and `*T` are references of either mutability,
|
|
|
|
|
|
|
|
and where unsize_kind(`T`) is the kind of the unsize info
|
|
|
|
|
|
|
|
in `T` - the vtable for a trait definition (e.g. `fmt::Display` or
|
|
|
|
|
|
|
|
`Iterator`, not `Iterator<Item=u8>`) or a length (or `()` if `T: Sized`).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Note that lengths are not adjusted when casting raw slices -
|
|
|
|
Note that lengths are not adjusted when casting raw slices -
|
|
|
|
`T: *const [u16] as *const [u8]` creates a slice that only includes
|
|
|
|
`*const [u16] as *const [u8]` creates a slice that only includes
|
|
|
|
half of the original memory.
|
|
|
|
half of the original memory.
|
|
|
|
|
|
|
|
|
|
|
|
Casting is not transitive, that is, even if `e as U1 as U2` is a valid
|
|
|
|
Casting is not transitive, that is, even if `e as U1 as U2` is a valid
|
|
|
|