由于类型错误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("")
}
}
这个问题类似于the one here,但尚未得到回答。
答案 0 :(得分:4)
问题是MyHashGenerator
没有采用类型参数。所以你做了一个承诺“相同的类型MyHashGenerator
就足够作为一个哈希生成器,并且无论T
如何都会以完全相同的方式行事”。 self.hash("")
是hash
上对HashGenerator
的调用,但Rust并不一定知道HashGenerator
是相同的 hash_node
实例被叫了。您可以通过以下两种方式之一明确说明此要求。
选项1:显式类型参数
通过明确告诉Rust参数是什么,可以避免这个问题。
fn hash_node(&self) -> u64 {
HashGenerator::<T>::hash(self, "")
}
现在它知道专门调用<T>
实例,这就足够了。
选项2:幻像数据
您可以将MyHashGenerator
参数化为(未使用的)T
参数。
use std::marker::PhantomData
...
struct MyHashGenerator<T> {
foo: PhantomData<T>
}
然后Rust可以根据self
的类型推断出您想要的实例,只要您将实例声明为
impl<T: Clone + Eq + Hash + ToString> HashGenerator<T> for MyHashGenerator<T> {
...
}
然后您不必更改hash_size
的实现。
就个人而言,我推荐选项1.它不是那么漂亮,但它提供了额外的API保证,事实上无论T
如何,事情都会以相同的方式工作。但是,如果您认为MyHashGenerator
稍后可能会使用T
参数(或者如果现在这样做,并且您的MCVE中没有包含该参数),您可以考虑使用选项2来实现该依赖关系更清楚。