Если вы используете as
для приведения числа с плавающей запятой к целочисленному типу, а число с плавающей запятой не подходит ¹ в типе назначения, результатом будет неопределенное значение², и большинство вещей, которые вы можете сделать с помощью это вызывает неопределенное поведение.
Это, безусловно, неудачно! Это проблема # 10184 на GitHub, и это один из немногих способов, которыми вы можете все еще вызывать неопределенное поведение в безопасном Rust. На самом деле, это самая старая ошибка в Rust.
Сегодня, если вы запускаете Rust с флагом -Z saturating-float-casts
, вместо этого с плавающей точкой в целочисленное значение выполняется насыщение (то есть слишком большие или маленькие значения преобразуется в T::MAX
или T::MIN
соответственно; NaN преобразуется в 0). Включение этого флага, скорее всего, замедлит большинство приведений с плавающей запятой, поскольку они должны сначала проверять границы типов, поэтому по умолчанию он еще не включен. Однако в будущем следует ожидать, что безопасное, но более медленное насыщение станет поведением as
, и появится новый API для ручного использования быстрого преобразования, но - unsafe
.
(Раньше существовала похожая проблема для определенных приведений к целочисленным значениям , но она была решена путем насыщения таких приведений всегда. Это изменение не считалось снижением производительности, и нет способ выбрать старое поведение.)
Также читайте
¹ «Подгонка» здесь означает либо NaN, либо число такой большой величины, что оно не может быть аппроксимировано меньшим типом. 8.7654321_f64
все равно будет усечен до 8
приведением as u8
, даже если значение не может быть точно представлено целевым типом - потеря точности не приводит к неопределенному поведению, а только вне диапазона.
² «Ядовитое» значение в LLVM, как вы правильно заметили в вопросе, но сама Rust не различает guish между undef
и отравляющими значениями.