如何使外部递归类型可插入到 HashSet 中
我使用 https://github.com/dtolnay/clang-ast 来解析生成的 JSON由 Clang 表示可用作 Rust 数据类型的 AST,特别是 Node
。我想将树中的节点(Node
是递归结构)插入到 HashSet
中。我什至无法插入根注释:
use std::collections::HashSet;
use log::debug;
use std::env;
use serde::Deserialize;
pub type Node = clang_ast::Node<Clang>;
#[derive(Deserialize)]
#[derive(Debug)]
pub enum Clang {
BinaryOperator(BinaryOperator),
Other,
}
#[derive(Deserialize, Debug)]
pub struct BinaryOperator {
pub opcode: String,
pub range: clang_ast::SourceRange,
}
fn main() {
env_logger::init();
let json = std::fs::read_to_string("ast.json").unwrap();
let node :Node = serde_json::from_str(&json).unwrap();
let mut node_set = HashSet::new();
node_set.insert(node);
}
这导致编译失败:
error[E0277]: the trait bound `clang_ast::Node<Clang>: Eq` is not satisfied
--> src/main.rs:28:21
|
28 | node_set.insert(node);
| ------ ^^^^ the trait `Eq` is not implemented for `clang_ast::Node<Clang>`
| |
| required by a bound introduced by this call
|
note: required by a bound in `HashSet::<T, S>::insert`
...
因此,我尝试使用添加 Eq
和 PartialEq
实现(遵循 如何为我自己的结构实现 Eq 和 Hash 以将它们用作 HashMap 键?):
impl PartialEq for Node {
fn eq(&self, other: &Self) -> bool {
self.id == other.id
}
}
impl Eq for Node {}
但是这失败了与:
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
--> src/main.rs:8:1
|
8 | impl PartialEq for Node {
| ^^^^^---------^^^^^----
| | | |
| | | `clang_ast::Node` is not defined in the current crate
| | `clang_ast::Node` is not defined in the current crate
| impl doesn't use only types from inside the current crate
|
= note: define and implement a trait or new type instead
我该如何进行这项工作?另外,为什么语言/编译器要施加这样的限制?
遵循为外来类型实现外来特征上的答案并没有真正帮助,因为有拼图的更多部分(实现 Eq
、PartialEq
、Hash
特征,处理递归性质clang_ast::注意
)。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
定义一个新类型包装器,例如 struct Node(clang:ast::Node)。
,或者在clang_ast::Node
上实现该特征,而不仅仅是clang_ast::Node
1.连贯性。结构的特征应该只有一种实现(忽略专业化)。允许板条箱在它们未定义的类型上实现它们未定义的特征,这可能会导致冲突和不连贯(其中一个依赖项使用一种实现,而另一个库使用另一种不兼容的实现),如果它们与以不同的方式处理相同的对象(例如某种通用集合,如哈希集)。
但这里按照 实现一致性规则只要没有 Clang 就是本地类型rel="nofollow noreferrer">未发现的类型 作为其参数之一出现,应该没问题(我无法在操场上测试它,因为
clang_ast
是那里的数字较小,但它与Box
一起工作得很好)。在其他上下文中(例如
Box
)重叠也可能是一个问题,但这里clang_ast::Node
没有实现PartialEq 根本没有,甚至没有条件。在那之前没有问题。
[1]:顺便说一句,您可能想报告错误消息具有误导性,因为Node
是一个泛型类型,我认为 Rust 接受这种尝试是没有意义的。事实上,我无法重现它,在操场上尝试impl PartialEq for Box
失败,并显示“错误[E0107]:缺少结构Box
的泛型”。编辑:构造出完全不正确的位,我认为一致性规则没有实际严格(仅适用于
Box
、Pin
和引用类型) 。Define a newtype wrapper e.g.
struct Node(clang:ast::Node<Clang>)
., or implement the trait onclang_ast::Node<Clang>
rather than justclang_ast::Node
1.Coherence. There should be only one implementation of a trait for a struct (ignoring specialisation). Allowing crates to implement traits they didn't define on types they didn't define is an opportunity for conflicts and incoherences (where one dependency uses one implementation and an other library uses an other incompatible implementation) which could lead to unsafety if they interact with the same objects in different ways (e.g. a generic collection of some sort, like a hashset).
Here though per the implementation coherence rules since
Clang
is a local type as long as there are no uncovered types appearing as one of its parameters it should be fine (I could not test this on the playground asclang_ast
is to minor to figure there, but it works fine withBox
).In other contexts (like
Box
) overlapping can also be an issue, but hereclang_ast::Node
does not implementPartialEq
at all, not even conditionally. Until that happens there's no issue.[1]: incidentally you may want to report that the error message is misleading, sinceNode
is a generic type I don't think it makes sense that Rust accepts this attempt. In fact I can not reproduce it, on the playground trying toimpl PartialEq for Box
fails with "error[E0107]: missing generics for structBox
".edit: struct out the completely incorrect bits where I thought the coherence rules were less strict than they actually are (which is only the case for
Box
,Pin
, and reference types).