-
-
Notifications
You must be signed in to change notification settings - Fork 475
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ast: Derive Hash
and PartialEq
on AST node types
#5283
Comments
This stupid code is affecting Rolldown to use impl Hash for Span {
fn hash<H: Hasher>(&self, _state: &mut H) {
// hash to nothing so all ast spans can be comparable with hash
}
} Moving to the main repo as this is a real issue. |
Hash
and PartialEq
on AST node typesHash
and PartialEq
on AST node types
Once this is done, we can replace this hash comparison of expressions to use oxc/crates/oxc_linter/src/ast_util.rs Lines 10 to 14 in 23e8456
|
@Boshen What do you think about my thought above under "Use different traits?" section? I think it's confusing to implement I suggest:
If we want to, later on we could also implement |
👍 for removing confusing
|
I find "partial" confusing, but it seems to mean a different kind of "partial" from "these 2 values are equal considering only part of them". From
I take this as meaning that |
I gave the definition of Partial equivalence relation a read, It states
Given that our equivalence relation between AST nodes is both symmetric and transitive I wonder maybe My math is pretty rusty but here's what I understand. Here are the properties of a "PER" A. Here's my reasoning These aren't proof or anything. A. For a set of AST nodes there is always a With that in mind, I feel we have both requirements of being a Partial Equivalence Relation which are:
You may argue that in most of our use cases, we are |
😵 My take on this is what |
Give it some thought and let me know which direction you want this to go. Implementing it using our new
If we want to go with /// 2 AST nodes are partially equal even when they don't share the same code span.
trait AstEq<T>: PartialEq<T> { } This would work as a self-documenting super trait so we can describe our custom derive behavior with explicit docs comments and a custom name so we can use it in the nominal contexts if we ever want to not use the |
Shall we go with |
So It'd be something like this for comparison? if a.content_eq(b) {
// ....
}
// -------------
if !a.content_ne(b) {
// ...
} Or is it still a super trait of |
Shall we go for
I had nightmares when I worked with with operator overloading in C++ 😁 |
Holy flipping christ! Well I can't argue with that 🥲 Concerning the super trait: If we make If that's correct, I suggest that we don't implement Obviously Incidentally, I agree with your choice of |
How are things like this working when our span hash implementation is noop? Line 395 in c984219
|
I agree, We should avoid implementing PartialEq where it doesn't make sense. |
It's stored as an array in the hashmap, it'll still use We have a few cases in Rolldown as well. |
I suspected that it was working because of PartialEq
Right now I'm trying to remove unnecessary hash implementations in the AST, The final result should implement a normal hash trait for the |
@Boshen Didn't Graphite implement closing issues after their respective PR is merged? |
Nope, it's something else ... they close referenced PRs from PRs 🤷 |
😆 I thought that was a bug since they've added this feature recently. It doesn't make sense to close a PR because a comment from it is mentioned with the word "fixes". |
Continuation from #3819
We should derive
Hash
andPartialEq
on all AST node types.Why?
The reasons we need to codegen them are (copied from #3819 (comment)):
Hash
We want
Hash
to skipspan
fields, and alsosymbol_id
etc. SkippingHash
is currently achieved by a dummyHash
impl onSpan
type:oxc/crates/oxc_span/src/span.rs
Lines 309 to 313 in 1b91d40
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 thespan
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 pointlessif
branches e.g.if (x) {} else if (x) { /* unreachable */ }
. But actuallyHash
is not ideal for this use -PartialEq
would be more efficient.But it's hard to implement
PartialEq
because, again, we need to skipspan
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
andPartialEq
, should we be more explicit about what these trait implementations do, and call themHashContent
andPartialEqContent
?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 donode1.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)
The text was updated successfully, but these errors were encountered: