-
-
Notifications
You must be signed in to change notification settings - Fork 930
Description
Continuation from #3819
We should derive Hash and PartialEq on all AST node types.
Why?
The reasons we need to codegen them are (copied from #3819 (comment)):
Hash
We want Hash to skip span fields, and also symbol_id etc. Skipping Hash is currently achieved by a dummy Hash impl on Span type:
oxc/crates/oxc_span/src/span.rs
Lines 309 to 313 in 1b91d40
| impl Hash for Span { | |
| fn hash<H: Hasher>(&self, _state: &mut H) { | |
| // hash to nothing so all ast spans can be comparable with hash | |
| } | |
| } |
I saw this as a bit of a hack, and thought it would be more "proper" solution to implement Hash on all AST types with the span field explicitly skipped. That would be laborious and error-prone to do by hand, but much easier with codegen.
PartialEq
The reason why we are implementing Hash on AST types is for (if I remember right) comparing expressions in a lint rule to identify pointless if branches e.g. if (x) {} else if (x) { /* unreachable */ }. But actually Hash is not ideal for this use - PartialEq would be more efficient.
But it's hard to implement PartialEq because, again, we need to skip span fields, and the no-op hash hack isn't viable here, so we can't use #[derive(PartialEq)].
So I thought we could do that with codegen.
Use different traits?
Instead of implementing Hash and PartialEq, should we be more explicit about what these trait implementations do, and call them HashContent and PartialEqContent?
PartialEq could then also be implemented on AST nodes for when you want to == check if 2 AST nodes are the same including their spans. And when you compare 2 nodes without spans, you have to do node1.eq_content(&node2) so it's explicit that spans aren't included in the comparison.
I'm not sure if this is a good idea or not.
Other useful info
rzvxa provided some useful background on how Rust's internal derive macros work: #3819 (comment)
Metadata
Metadata
Assignees
Labels
Type
Fields
Give feedbackPriority