没有注释

时间:2018-03-28 14:54:07

标签: 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("")
    }
}

Code on Playground.

这个问题类似于the one here,但尚未得到回答。

1 个答案:

答案 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来实现该依赖关系更清楚。