Поскольку этот ответ был создан, было решено , чтобы реализация TryFrom<usize>
всегда учитывала возможность отказа, независимо от текущей платформы.Оригинальный код теперь успешно компилируется в Rust 1.34.
Оригинальный ответ
наличие TryFrom<usize>
для u32
зависит от наличия From<usize>
для u32
, что мне кажется несколько странным
Это потому, что есть общая реализация TryFrom
для всего, что реализует From
:
impl<T, U> TryFrom<U> for T
where
T: From<U>,
{
type Error = !;
}
Как вы упомянули, поскольку Rust поддерживает платформы, где собственная целая длина составляет 16, 32 или 64биты, имеющие такую реализацию From
/ Into
не будут без потерь на некоторых из этих платформ.
Эта ошибка возникает из-за отсутствия прямой реализации TryFrom
/ TryInto
для этих типов.Это связано с тем, что пользователи этих характеристик предпочитают, чтобы реализации были безошибочными, когда они соответствуют платформе (type Error = !
).
Существует отдельная проблема отслеживания 49415 специально для решения этой проблемы.
Я думаю, что могу написать свою собственную функцию, которая выполняет преобразование
Да, это то, что вы должны делать.Что-то вроде этого непроверенного фрагмента кода:
use std::u32;
struct SomeError;
// usize is a u16 or u32, which always fits in a u32
#[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))]
fn my_thing(a: usize) -> Result<u32, SomeError> {
Ok(a as u32)
}
// usize is a u64, which might be too big
#[cfg(target_pointer_width = "64")]
fn my_thing(a: usize) -> Result<u32, SomeError> {
if a > u32::MAX as usize {
Err(SomeError)
} else {
Ok(a as u32)
}
}
Я был бы удивлен, если бы у Rust не было идиоматического способа сделать это преобразование.В конце концов, usize
и u32
- это два основных типа.
Проблема в том, что usize
на самом деле не является "базовым" типом, поскольку он меняет размер в зависимости от целевой платформы.Получить правильную, эргономичную и нелегко.