Merge pull request #287 from JohnTitor/casting

Remove casting list from the nomicon
pull/291/head
Eric Huss 3 years ago committed by GitHub
commit ca4aa393d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,65 +1,34 @@
# Casts # Casts
Casts are a superset of coercions: every coercion can be explicitly Casts are a superset of coercions: every coercion can be explicitly invoked via a cast.
invoked via a cast. However some conversions require a cast. However some conversions require a cast.
While coercions are pervasive and largely harmless, these "true casts" While coercions are pervasive and largely harmless, these "true casts" are rare and potentially dangerous.
are rare and potentially dangerous. As such, casts must be explicitly invoked As such, casts must be explicitly invoked using the `as` keyword: `expr as Type`.
using the `as` keyword: `expr as Type`.
True casts generally revolve around raw pointers and the primitive numeric You can find an exhaustive list of [all the true casts][cast list] and [casting semantics][semantics list] on the reference.
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 must be valid
at the type level, or else they will be prevented statically. For instance,
`7u8 as bool` will not compile.
That said, casts aren't `unsafe` because they generally can't violate memory ## Safety of casting
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 `*` True casts generally revolve around raw pointers and the primitive numeric types.
to denote either a `*const` or `*mut`, and `integer` to denote any integral Even though they're dangerous, these casts are infallible at runtime.
primitive: If a cast triggers some subtle corner case no indication will be given that this occurred.
The cast will simply succeed.
That said, casts must be valid at the type level, or else they will be prevented statically.
For instance, `7u8 as bool` will not compile.
* `*T as *U` where `T, U: Sized` That said, casts aren't `unsafe` because they generally can't violate memory safety *on their own*.
* `*T as *U` TODO: explain unsized situation For instance, converting an integer to a raw pointer can very easily lead to terrible things.
* `*T as integer` However the act of creating the pointer itself is safe, because actually using a raw pointer is already marked as `unsafe`.
* `integer as *T`
* `number as number`
* `field-less enum as integer`
* `bool as integer`
* `char as integer`
* `u8 as char`
* `&[T; n] as *const T`
* `fn as *T` where `T: Sized`
* `fn as integer`
Note that lengths are not adjusted when casting raw slices - ## Some notes about casting
`*const [u16] as *const [u8]` creates a slice that only includes
half of the original memory.
Casting is not transitive, that is, even if `e as U1 as U2` is a valid ### Lengths when casting raw slices
expression, `e as U2` is not necessarily so.
For numeric casts, there are quite a few cases to consider: Note that lengths are not adjusted when casting raw slices; `*const [u16] as *const [u8]` creates a slice that only includes half of the original memory.
* casting between two integers of the same size (e.g. i32 -> u32) is a no-op ### Transitivity
(Rust uses 2's complement for negative values of fixed integers)
* casting from a larger integer to a smaller integer (e.g. u32 -> u8) will Casting is not transitive, that is, even if `e as U1 as U2` is a valid expression, `e as U2` is not necessarily so.
truncate
* casting from a smaller integer to a larger integer (e.g. u8 -> u32) will [cast list]: ../reference/expressions/operator-expr.html#type-cast-expressions
* zero-extend if the source is unsigned [semantics list]: ../reference/expressions/operator-expr.html#semantics
* sign-extend if the source is signed
* casting from a float to an integer will round the float towards zero and
produces a "saturating cast" when the float is outside the integer's range
* floats that are too big turn into the largest possible integer
* floats that are too small produce the smallest possible integer
* NaN produces zero
* casting from an integer to float will produce the floating point
representation of the integer, rounded if necessary (rounding to
nearest, ties to even)
* casting from an f32 to an f64 is perfect and lossless
* casting from an f64 to an f32 will produce the closest possible value
(rounding to nearest, ties to even)

Loading…
Cancel
Save