Pie*_*ine 1 type-inference traits rust
我有一个关联类型的特征:
pub trait Speak {
type Error;
fn speak(&self) -> Result<String, Self::Error>;
}
Run Code Online (Sandbox Code Playgroud)
该特征的实现:
#[derive(Default)]
pub struct Dog;
impl Speak for Dog {
type Error = ();
fn speak(&self) -> Result<String, Self::Error> {
Ok("woof".to_string())
}
}
Run Code Online (Sandbox Code Playgroud)
并且函数返回该实现的实例:
pub fn speaker() -> impl Speak {
Dog::default()
}
Run Code Online (Sandbox Code Playgroud)
我知道在这个例子中我只能Dog用作返回类型,但在我的实际代码中我必须使用impl Speak(上面的函数实际上是由宏生成的).
据我了解,该impl Trait符号让出这实际上返回具体类型编译器的身影,所以我希望下面的函数正确编译,因为speaker()回报Dog,并且Dog::Error是类型():
fn test() -> Result<String, ()> {
speaker().speak()
}
Run Code Online (Sandbox Code Playgroud)
相反,我收到以下错误:
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>`
Run Code Online (Sandbox Code Playgroud)
就好像编译器不能(在这一点上)推断出speaker函数的返回类型.
谁错过了某些东西,编译器或我自己?
使用-> impl Speak<Error = ()>作为返回类型speaker().
问题是编译器只需要签名就需要足够的信息,调用者可以实际使用该函数.如果你只是返回impl Speak,那么编译器知道speak()返回a Result<String, ???>- 错误类型未知,因此编译器发出错误.
编译器无法在此推断任何内容.它无法从呼叫站点推断出错误类型,因为impl Trait返回位置不允许来自呼叫站点的推断.它无法从实现中推断出错误类型,因为这意味着调用者类型检查是否取决于实现,而不是如何impl Trait工作.呼叫者必须始终只在签名信息的情况下进行类型检查; 之后只插入混凝土类型.