Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What casts are allowed with `as`?

Tags:

casting

rust

The Rust Book section on the as operator currently says

The as keyword does basic casting:

let x: i32 = 5;

let y = x as i64;

It only allows certain kinds of casting, however.

What are those certain kinds of allowed casting?

A since-deleted answer here explained that sometimes you need to chain multiple as-casts to accomplish a safe result, that can't be done in a single step. When is that necessary?

like image 965
poolie Avatar asked Nov 24 '15 01:11

poolie


2 Answers

I don't think that this is documented very well, but here is some information you might find useful:

A cast e as U is valid if one of the following holds:

  • e has type T and T coerces to U; coercion-cast
  • e has type *T, U is *U_0, and either U_0: Sized or unsize_kind(T) = unsize_kind(U_0); 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 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
  • 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

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 - T: *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 expression, e as U2 is not necessarily so (in fact it will only be valid if U1 coerces to U2).

like image 58
Adrian Avatar answered Nov 15 '22 11:11

Adrian


Quoted from The Rustonomicon: Casts

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 primitive:

  • *T as *U where T, U: Sized
  • *T as *U TODO: explain unsized situation
  • *T as integer
  • integer as *T
  • number as number
  • C-like-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
like image 2
WiSaGaN Avatar answered Nov 15 '22 11:11

WiSaGaN