为什么编译器不推断 impl trait 返回值的关联类型的具体类型? [英] Why does the compiler not infer the concrete type of an associated type of an impl trait return value?

查看:32
本文介绍了为什么编译器不推断 impl trait 返回值的关联类型的具体类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a trait with an associated type:

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())
    }
}

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

And a function returning an instance of that implementation:

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

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

I know that in this example I could just use Dog as the return type, but in my actual code I have to use impl Speak instead (the above function is in fact generated by a macro).

据我所知,impl Trait 表示法让编译器确定实际返回的是哪个具体类型,因此我希望以下函数能够正确编译,因为 speaker() 返回一个 Dog 并且 Dog::Error 是类型 ():

As I understand it, the impl Trait notation lets the compiler figure out which concrete type is actually returned, so I would expect the following function to compile correctly because speaker() returns a Dog and that Dog::Error is the type ():

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

游乐场

相反,我收到以下错误:

Instead, I get the following error:

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 函数的返回类型.

It is as if the compiler could not (at this point) infer the return type of the speaker function.

谁遗漏了什么,是编译器还是我自己?

Who is missing something something, the compiler or myself?

推荐答案

使用 ->impl Speak 作为speaker()的返回类型.

Use -> impl Speak<Error = ()> as the return type of speaker().

问题是编译器需要,仅从签名中就需要足够的信息,以便调用者可以实际使用该函数.如果你只返回 impl Speak,那么编译器知道 speak() 返回一个 Result - 错误类型未知,因此编译器会发出错误.

The problem is that the compiler needs, from the signature alone, enough information that the caller can actually use the function. If you just return impl Speak, then the compiler knows that speak() returns a Result<String, ???> - the error type isn't known, and thus the compiler issues an error.

编译器无法在这里推断出任何东西.它无法从调用站点推断错误类型,因为返回位置的 impl Trait 不允许来自调用站点的推断.它无法从实现推断错误类型,因为这意味着调用者类型检查是否取决于实现,而 impl Trait 不是这样工作的.调用者必须始终在仅存在签名信息的情况下进行类型检查;之后才插入具体类型.

The compiler cannot infer anything here. It cannot infer the error type from the call site, because impl Trait in return position doesn't allow inference from the call site. It cannot infer the error type from the implementation, because that would mean whether the caller type-checks depends on the implementation, and that's not how impl Trait works. The caller must always type-check in presence of only the information of the signature; the concrete type is only plugged in after that.

这篇关于为什么编译器不推断 impl trait 返回值的关联类型的具体类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆