繁体   English   中英

为什么编译器不推断impl特质返回值的关联类型的具体类型?

[英]Why does the compiler not infer the concrete type of an associated type of an impl trait return value?

我有一个关联类型的特征:

pub trait Speak {
    type Error;
    fn speak(&self) -> Result<String, Self::Error>;
}

该特征的实现:

#[derive(Default)]
pub struct Dog;

impl Speak for Dog {
    type Error = ();
    fn speak(&self) -> Result<String, Self::Error> {
        Ok("woof".to_string())
    }
}

一个函数返回该实现的实例:

pub fn speaker() -> impl Speak {
    Dog::default()
}

我知道在此示例中,我可以仅使用Dog作为返回类型,但是在我的实际代码中,我必须使用impl Speak代替(上面的函数实际上是由宏生成的)。

据我了解, impl Trait表示法使编译器可以弄清楚实际返回的是哪种具体类型,因此我希望以下函数能够正确编译,因为speaker()返回Dog ,而Dog::Error是type ()

fn test() -> Result<String, ()> {
    speaker().speak()
}

操场

相反,我收到以下错误:

error[E0308]: mismatched types
  --> src/lib.rs:21:5
   |
20 | fn test() -> Result<String, ()> {
   |              ------------------ expected `std::result::Result<std::string::String, ()>` because of return type
21 |     speaker().speak()
   |     ^^^^^^^^^^^^^^^^^ expected (), found associated type
   |
   = note: expected type `std::result::Result<_, ()>`
              found type `std::result::Result<_, <impl Speak as Speak>::Error>`

好像编译器无法(此时)推断出speaker函数的返回类型。

谁缺少某些东西,编译器还是我自己?

使用-> impl Speak<Error = ()>作为返回类型speaker()

问题在于,编译器仅从签名就需要调用者可以实际使用该函数的足够信息。 如果仅返回impl Speak ,则编译器知道speak()返回Result<String, ???> -错误类型未知,因此编译器会发出错误。

编译器无法在此处推断任何内容。 它不能从呼叫站点推断错误类型,因为在返回位置的impl Trait不允许从呼叫站点推断错误。 它不能从实现中推断出错误类型,因为这将意味着调用者的类型检查是否取决于实现,而这不是impl Trait工作方式。 调用者必须始终仅在签名信息存在的情况下进行类型检查; 此后才插入具体类型。

你是。

您从未指定关联的Error类型,因此您不能承担任何责任。 即使确实是() ,编译器也不允许您使用该知识。 要解决此问题,只需指定Error是什么:

pub fn speaker() -> impl Speak<Error = ()> {
    Dog::default()
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM