为什么我不能将 U::from 与 T: Into<U> 约束一起使用?

问题描述 投票:0回答:2

我想要一个简单的类型转换,我认为代码应该如下所示:

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> {
   |                                                          ++++++++++++++++++++++

我不明白我的代码问题出在哪里。我知道

From
Into
特征是相关的,如果我实现
From
Into
将自动实现,但我不明白为什么
Celsius
应该是泛型类型。

也许这段代码会更惯用(至少这段代码可以编译):

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

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

generics rust traits
2个回答
3
投票

你是对的,任何实现

From
的东西都会自动提供自反
Into
实现,这意味着任何
From
转换都可以使用
.into()
,但相反则不然;类型可以实现
Into
但没有自反
From
实现。

使用

Into
(而不是
From
)作为函数参数是惯用的,因此您应该像上一个代码片段一样在函数体内使用
.into()


0
投票

如果您的问题是为什么

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

© www.soinside.com 2019 - 2024. All rights reserved.