Rust无法在没有注释的情况下推断类型

sni*_*im2 2 types rust

由于类型错误,下面的代码无法编译error[E0283]: type annotations required: cannot resolve _: std::cmp::Eq。要编译此代码,需要哪种类型的注释?

此示例代码来自一个更大的程序,该程序MyHashGenerator::hash_node()用于哈希AST中的节点(类型T与AST节点中保存的值有关,但不需要AST的定义来重现类型错误)。

use std::hash::Hash;

pub trait HashGenerator<T: Clone + Eq + Hash + ToString> {
    fn hash(&self, msg: &str) -> u64;  // Hash a string.
    fn hash_node(&self) -> u64;  // Hash an AST node.
}

struct MyHashGenerator {}

impl<T: Clone + Eq + Hash + ToString> HashGenerator<T> for MyHashGenerator {
    fn hash(&self, msg: &str) -> u64 {
        0
    }

    fn hash_node(&self) -> u64 {
        // error[E0283]: type annotations required: cannot resolve `_: std::cmp::Eq`
        self.hash("")
    }
}
Run Code Online (Sandbox Code Playgroud)

在操场上的代码。

此问题与此处的问题类似,但尚未得到解答。

Sil*_*olo 5

问题是MyHashGenerator没有类型参数。因此,您可以保证“ 相同的类型MyHashGenerator足以满足哈希生成器的要求,并且无论如何都将具有完全相同的方式。Tself.hash("")是对hashon 的调用HashGenerator,但是Rust不一定知道它 被调用的HashGenerator实例相同hash_node。您可以通过以下两种方式之一明确要求。

选项1:显式类型参数

通过显式告诉Rust参数是什么,您可以避免此问题。

fn hash_node(&self) -> u64 {
    HashGenerator::<T>::hash(self, "")
}
Run Code Online (Sandbox Code Playgroud)

现在,它知道要专门调用该<T>实例,这就足够了。

选项2:虚拟数据

您可以参数化MyHashGenerator以具有(未使用的)T参数。

use std::marker::PhantomData

...

struct MyHashGenerator<T> {
    foo: PhantomData<T>
}
Run Code Online (Sandbox Code Playgroud)

然后Rust可以根据的类型推断您想要的实例self,只要您将实例声明为

impl<T: Clone + Eq + Hash + ToString> HashGenerator<T> for MyHashGenerator<T> {
    ...
}
Run Code Online (Sandbox Code Playgroud)

然后,您不必更改的实现hash_size

就个人而言,我建议使用选项1。它虽然不那么漂亮,但是它提供了额外的API保证,无论事实如何,事物实际上都将以相同的方式工作T。但是,如果您认为以后MyHashGenerator可能会使用该T参数(或者现在使用该参数,而MCVE中根本没有包含该参数),则可以考虑使用选项2来使该依赖性更加清晰。