我有一个关联类型的特征:
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
是类型 ()
:
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
的方式。作品。调用者必须始终在仅存在签名信息的情况下进行类型检查;具体类型仅在此之后插入。
关于rust - 为什么编译器不推断 impl 特征返回值的关联类型的具体类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52831488/