rust 为什么不能将U::from与T:变成< U>约束?

kd3sttzy  于 2023-10-20  发布在  其他
关注(0)|答案(2)|浏览(132)

我想有一个简单的类型转换,我认为代码应该看起来像这样:

struct Celsius(f64);
struct Fahrenheit(f64);

impl From<Celsius> for Fahrenheit {
    fn from(c: Celsius) -> Self {
        Fahrenheit(c.0 * 9. / 5. + 32.)
    }
}

impl From<Fahrenheit> for Celsius {
    fn from(f: Fahrenheit) -> Self {
        Celsius((f.0 - 32.) * 5. / 9.)
    }
}

fn danger_of_freezing<T: Into<Celsius>>(temp: T) -> bool {
    let celsius = Celsius::from(temp);
    celsius.0 < 0.0
}

fn main() {
    danger_of_freezing(Celsius(20.0));
    danger_of_freezing(Fahrenheit(68.0));
}

但是编译器给了我这个给予:

error[E0277]: the trait bound `Celsius: From<T>` is not satisfied
  --> src\main.rs:17:33
   |
17 |     let celsius = Celsius::from(temp);
   |                   ------------- ^^^^ the trait `From<T>` is not implemented for `Celsius`
   |                   |
   |                   required by a bound introduced by this call
   |
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
   |
16 | fn danger_of_freezing<T: Into<Celsius>>(temp: T) -> bool where Celsius: From<T> {
   |                                                          ++++++++++++++++++++++

我不明白我的代码中的问题在哪里。我知道FromInto trait是相关的,如果我实现FromInto将自动实现,但我不明白为什么Celsius应该是泛型类型。
也许这段代码会更地道(至少这段代码可以编译):

fn danger_of_freezing<T: Into<Celsius>>(temp: T) -> bool {
    let celsius: Celsius = temp.into();
    celsius.0 < 0.0
}

但为什么第一个变体不起作用?

5lhxktic

5lhxktic1#

你是对的,任何实现From的东西都自动提供了一个自反的Into实现,这意味着任何From转换都可以使用.into(),但是 * 相反的情况不是真的 *;一个类型可以实现Into而不具有自反From实现。
使用Into(而不是From)作为函数参数是惯用的,因此您应该像上一个代码片段那样在函数体内使用.into()

busg9geu

busg9geu2#

如果你的问题是为什么Celsius::from(temp)给出一个错误.
在您的代码中,Celsius::from有两个方法实现

  1. Celsius::from(temp: Fahrenheit)您提供的
  2. Celsius::from(temp: Celsius)是通用的,因为From是自反的。
    所以这是有效的:
Celsius::from(Celsius(1.));
Celsius::from(Fahrenheit(1.));

而任何其他类型都不是,例如泛型类型T

相关问题