由于类型错误,下面的代码无法编译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)
此问题与此处的问题类似,但尚未得到解答。
问题是MyHashGenerator没有类型参数。因此,您可以保证“ 相同的类型MyHashGenerator足以满足哈希生成器的要求,并且无论如何都将具有完全相同的方式。T” self.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来使该依赖性更加清晰。