Почему преобразование размера Rust в u128 считается неудачным?

Взглянем:

use std::convert::{From, TryFrom};

fn main() {
  let size: usize = 42;
  let good: u128  = u128::try_from(size).unwrap(); // works fine
  let bad:  u128  = u128::from(size);              // doesn't compile!
}

Насколько я знаю, usize — целочисленный тип, и они никогда не превышают 128 бит. Поэтому я не вижу возможности, чтобы преобразование usize -> u128 могло потерпеть неудачу. Итак, почему u128 не реализует From<usize>?

Обновление: документация Rust говорит :

Из T для U подразумевается In U для T

Хотя usize -> u128 выглядит нормально, u128 -> usize нет. Хорошо, но почему вместо usize не реализовано Into<u128>?


person passing_through    schedule 10.07.2020    source источник
comment
usize — размер указателя. Теоретически у вас может быть система с адресным пространством, требующим более 128 бит для адресации... когда-нибудь. Проверка на будущее? ;-)   -  person T.J. Crowder    schedule 10.07.2020
comment
«От T для U подразумевает Into U для T» в этом случае будет означать, что и usize -> u128, и u128 <- usize подходят. Он ничего не говорит о u128 -> usize.   -  person mcarton    schedule 10.07.2020


Ответы (2)


Хотя usize -> u128 выглядит нормально, u128 -> usize — нет. Хорошо, но почему Into не реализован для использования вместо этого?

Потому что, несмотря на то, что для Rust гарантируется, что usize всегда будет не менее 16 бит, не гарантируется, что он всегда будет максимум 64 бита.

Маловероятно, что это когда-либо будет полезно, но технически ничто не препятствует 256-битным указателям, а поскольку размер usize гарантированно соответствует размеру указателя, это сделает преобразование usize -> u128 невозможным.

person Masklinn    schedule 10.07.2020
comment
Разве не было бы нормальным сделать его условно определенным, если размер использования целевой платформы составляет ‹= 128 бит. Так что он всегда есть и компилируется, но если вы когда-нибудь нацелитесь на сумасшедшую гипотетическую платформу с 256-битными указателями, она не будет определена, и ваша программа не скомпилируется. - person Eloff; 20.07.2021
comment
Нет, условное определение трейта core stdlib — это ненормально, по крайней мере, для стандартной библиотеки. Обычным делом для стандартной библиотеки является определение признаков расширения для конкретной платформы, что здесь не имеет значения. - person Masklinn; 20.07.2021
comment
мой подход кажется намного лучше, чем если бы трейт вообще не был определен для всех платформ, хотя на самом деле он в настоящее время может быть определен на всех поддерживаемых платформах. Есть прецедент для этого или нет, на самом деле не важно. - person Eloff; 22.07.2021
comment
Удобнее не значит лучше. И прецедент на самом деле важен, исчезновение основных черт является значительным изменением политики, а не безобидным расхождением во мнениях. Смотрите также: #37423, #70460 - person Masklinn; 22.07.2021

В документе From trait говорится

Примечание: эта черта не должна провалиться. Если преобразование может завершиться неудачей, используйте TryFrom.

Поскольку вы не знаете, может ли usize содержать значение u16/u32/u64/u128 (в зависимости от вашей цели компиляции), все эти примитивные типы реализуют TryFrom вместо From.

В документе Rust implies означает, что когда у вас есть тип, реализующий From, компилятор выдаст вам Into бесплатно (обратите внимание, что обратное неверно). Та же идея применима к TryFrom и TryInto. Таким образом, следующий код будет работать так, как ожидалось.

use std::convert::{TryFrom,TryInto};

fn main() {
  let size: usize = 42;
  let good: u128  = u128::try_from(size).unwrap();
  let doublegood:usize = good.try_into().unwrap();
}
person whilrun    schedule 10.07.2020
comment
Вы правы, но, пожалуйста, проверьте обновленный пост: почему usize не реализует Into<u128>? Я считаю, что это не подразумевает From (что было бы небезопасно) или что-то еще. - person passing_through; 10.07.2020
comment
@passing_through считает, что он предназначен для обеспечения согласованности, поскольку преобразование размера использования в u32, u16 и u8 не гарантируется на современном оборудовании. Rust смотрит в будущее, и мы можем увидеть, что однажды на ПК будут установлены 128-битные или 256-битные процессоры. Если этот день действительно настал, переход с usize на u128 тоже не будет безопасным. Таким образом, если Rust внедрил Into сегодня, его нужно изменить на TryInto, и любые программы, использующие эту функциональность, рискуют запаниковать или не работать полностью. Кроме того, у нас уже есть аккуратный as в ржавчине для небезопасных преобразований. - person whilrun; 10.07.2020