Inefficient implementation of `PartialEq` for nested (fieldless) enums
@dianqk is already working on this.
Since Nov 6, 2024.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
Description
I'm not sure if this is the right place for this (might be LLVM to blame), just a bit of inefficient code that I noticed.
https://godbolt.org/z/K57orYj5h
The only difference between the two functions eq and matches is the use of == and matches! for the enum comparison. The generated code for eq includes two calls to PartialEq for Outer, whereas the code for matches has a much simpler (inline) comparison.
Also, the generated code for PartialEq seems very inefficient, given the enum is just a two-byte value that can be directly compared.
If you tinker with the enum definitions it's not hard to cause eq to optimise exactly like matches.
Example copied here
#[derive(PartialEq)]
pub enum InnerInner {
One,
Two,
}
#[derive(PartialEq)]
pub enum Inner {
One,
Two,
Const(InnerInner),
}
#[derive(PartialEq)]
pub enum Outer {
One(Inner),
Two,
Three,
Four,
Five(Inner),
Six(Inner),
Seven(Inner),
Eight(Inner),
}
#[no_mangle]
pub fn eq(t: Outer, b: &mut bool) {
let token_type = if t == Outer::One(Inner::One) {
Outer::One(Inner::One)
} else {
Outer::Two
};
*b = token_type == Outer::Two;
}
#[no_mangle]
pub fn matches(t: Outer, b: &mut bool) {
let token_type = if matches!(t, Outer::One(Inner::One)) {
Outer::One(Inner::One)
} else {
Outer::Two
};
*b = matches!(token_type, Outer::Two);
}
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.