首页 \ 问答 \ 如果没有注释,Rust无法推断类型(Rust cannot infer type without annotation)

如果没有注释,Rust无法推断类型(Rust cannot infer type without annotation)

由于类型错误error[E0283]: type annotations required: cannot resolve _: std::cmp::Eq下面的代码无法编译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 code below cannot compile due to the type error error[E0283]: type annotations required: cannot resolve _: std::cmp::Eq. What type annotation is needed in order to compile this code?

This example code is taken from a much larger program where MyHashGenerator::hash_node() is used to hash nodes in an AST (the type T relates to a value that is held inside AST nodes, but the definition of the AST is not needed to reproduce the type error).

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.

This question is similar to the one here, which has not been answered.


原文:https://stackoverflow.com/questions/49537809
更新时间:2019-12-13 08:11

最满意答案

问题是MyHashGenerator没有采用类型参数。 所以你做了一个承诺“ 相同的类型MyHashGenerator就足以作为一个哈希生成器,并且无论T如何都会以完全相同的方式运行”。 self.hash("")是对HashGenerator hash调用,但Rust并不一定知道它 HashGenerator实例相同 。 您可以通过以下两种方式之一明确说明此要求。

选项1:显式类型参数

通过明确告诉Rust参数是什么,可以避免这个问题。

fn hash_node(&self) -> u64 {
    HashGenerator::<T>::hash(self, "")
}

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

选项2:幻像数据

您可以将MyHashGenerator参数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来使该依赖关系更加清晰。


The problem is MyHashGenerator doesn't take a type argument. So you're making a promise "The same type MyHashGenerator will suffice as a hash generator and will behave the exact same way regardless of T". self.hash("") is a call to hash on HashGenerator, but Rust doesn't necessarily know that it's the same HashGenerator instance that hash_node was called on. You can make this requirement explicit in one of two ways.

Option 1: Explicit Type Arguments

By explicitly telling Rust what the arguments are, you can avoid this problem.

fn hash_node(&self) -> u64 {
    HashGenerator::<T>::hash(self, "")
}

Now it knows to call specifically the <T> instance, which will suffice.

Option 2: Phantom data

You can parameterize MyHashGenerator to have an (unused) T parameter.

use std::marker::PhantomData

...

struct MyHashGenerator<T> {
    foo: PhantomData<T>
}

Then Rust can infer which instance you want based on the type of self, so long as you declare your instance as

impl<T: Clone + Eq + Hash + ToString> HashGenerator<T> for MyHashGenerator<T> {
    ...
}

Then you don't have to change your implementation of hash_size.

Personally, I recommend Option 1. It's not as pretty, but it provides the additional API guarantee that things will in fact work the same way regardless of T. However, if you think MyHashGenerator might use the T argument later (or if it does now, and that simply wasn't included in your MCVE), you may consider going with Option 2 to make that dependency more clear.

2018-03-28

相关文章

更多

最新问答

更多
  • 删除不适用于JSP中使用for循环的每个id(Deletion not working for every id using for loop in JSP)
  • 如何从std :: filesystem :: path中删除引号(How to remove quotation marks from std::filesystem::path)
  • 验证多个控制器方法的URL路径(Validate URL path for several controller methods)
  • 如何在datarow []中的列中找到最大值?(How to find max value in a column in a datarow[] ?)
  • 如何使用预定义文本替换来自数据库的部分结果(How do I replace part of result coming from Database with predefined text)
  • Selenium Java注入了新的Javascript函数(Selenium Java inject new Javascript function)
  • 使用.on的多个下拉菜单选择文本仅适用于第一个下拉列表(Multiple Dropdowns Menu Selection text using .on works only on first dropdown)
  • 快速将黄土曲线添加到大型数据集图中的方法(Quick way to add loess curve to large data set graph)
  • FilteringSelect in mvc(FilteringSelect in mvc)
  • 在Delphi XE2中开发Mac或iOS应用程序需要哪些硬件/软件?(What hardware/software is necessary to develop Mac or iOS apps in Delphi XE2?)
  • 在原型的构造函数中初始化属性时获取“未定义”(Getting 'undefined' when a property is initialized in the constructor of a prototype)
  • 通过越狱加载的应用程序的Documents文件夹位置(Location of Documents folder for an app loaded via jailbreak)
  • 在OpenGL中使用可编程和固定管道功能(Using both programmable and fixed pipeline functionality in OpenGL)
  • 将任何用户输入重定向到单独的底层程序(redirect any user input to a separate underlying program)
  • 编辑文本不能正常工作android(Edit texts not working properly android)
  • “user_denied”Facebook应用页面上的Facebook用户区域设置(Facebook user locale on “user_denied” facebook app page)
  • 在大图像中找到小的部分透明图像的坐标(find coordinates of small partially-transparent image within a large image)
  • 我如何在cakephp 3.1中获得完整的相对路径?(How i can get full relative path of image in cakephp 3.1?)
  • 如何保存拖动标记的新本地化?(How to save new localization of dragged marker?)
  • MySQL UPDATE vs INSERT和DELETE(MySQL UPDATE vs INSERT and DELETE)
  • 在执行查询之前,在SQLAlchemy模型中将datetime转换为unix时间戳?(Convert datetime to unix timestamp in SQLAlchemy model before executing query?)
  • OpenCL与OpenGL互操作的优势(Advantage of OpenCL interoperability with OpenGL)
  • 如何解析用点和等分隔的数据然后添加到listview(How to parsing data from delimited with dot and equal then add to listview)
  • 带调试输出的X3解析器段错误(BOOST_SPIRIT_X3_DEBUG)(X3 parser segfaults with debug output (BOOST_SPIRIT_X3_DEBUG))
  • 将文件夹名称添加到fgrep结果(Add folder name to fgrep result)
  • 在MySQL中加载一个表是非常慢的(Loading one table in MySQL is ridiculously slow)
  • 如何将JSON放入PHP变量?(How do I put JSON into a PHP Variable?)
  • 如何绕过Microsoft.Speech.Recognition中的不流畅?(How to bypass disfluencies in Microsoft.Speech.Recognition?)
  • 原点的最后一行是什么?(What is the last row of an origin for?)
  • 将字符串转换为javascript中的操作(Translate String to operation in javascript)