Подтвердить что ты не робот

Какие броски разрешены с помощью `as`?

В разделе "Книга ржавчины" оператора as в настоящее время говорится

Ключевое слово as выполняет базовое кастинг:

let x: i32 = 5;

let y = x as i64;

Однако он допускает только определенные виды кастингов.

Каковы эти определенные виды разрешенных кастингов?

В результате ответа "с удалением" здесь объясняется, что иногда вам нужно связать несколько as -casts для достижения безопасного результата, что невозможно сделать за один шаг. Когда это необходимо?

4b9b3361

Ответ 1

Я не думаю, что это задокументировано очень хорошо, но здесь - это некоторая информация, которая может вам пригодиться:

Листинг e as U действителен, если выполнено одно из следующих действий:

  • e имеет тип T и T приводит к U; принуждении литая
  • e имеет тип *T, U - *U_0, и либо U_0: Sized, либо unsize_kind (T) = unsize_kind (U_0); PTR-PTR-литая
  • e имеет тип *T, а U - числовой тип, а T: Sized; PTR-адр-литая
  • e - целое число, а U - *U_0, а U_0: Sized; адр-PTR-литая
  • e имеет тип T и T и U - любые числовые типы; Числовой-литая
  • e является C-подобным перечислением, а U является целым типом; Перечисление-литая
  • e имеет тип bool или char и U - целое число; прима-ИНТ-литая
  • e имеет тип u8 и U is char; u8- char Литой
  • e имеет тип &[T; n] и U is *const T; массив PTR-литая
  • e - это тип указателя функции, а U имеет тип *T, а T: Sized; fptr-PTR-литая
  • e - это тип указателя функции, а U - целое число; fptr-адр-литая

где &.T и *T являются ссылками любой изменчивости, и где unsize_kind (T) - это тип unsize info в T - vtable для определения признака (например, fmt::Display или Iterator, а не Iterator<Item=u8>) или длину (или (), если T: Sized).

Обратите внимание, что при отбрасывании сырых срезов длины не корректируются - T: *const [u16] as *const [u8] создает срез, который включает только половину исходной памяти.

Кастинг не является транзитивным, то есть даже если e as U1 as U2 является действительным выражение, e as U2 не обязательно так (на самом деле оно будет справедливо только в том случае, если U1 приближается к U2).

Ответ 2

Цитата из The Rustonomicon: Casts

Вот исчерпывающий список всех настоящих бросков. Для краткости мы будем использовать * для обозначения a * const или * mut и integer для обозначения любого интегрального примитива:

  • * T как * U, где T, U: размер
  • * T как * U TODO: объясните нестандартную ситуацию
  • * T как целое
  • integer as * T
  • номер как номер
  • C-like-enum как целое
  • bool as integer
  • char как целое
  • u8 как char
  • & [Т; n] как * const T
  • fn as * T, где T: Sized
  • fn как целое