rust-lang / rust-lang/rust

Inefficient implementation of `PartialEq` for nested (fieldless) enums

Open
#132,628 12 comments 0 reactions 1 assignee View on GitHub

@dianqk is already working on this.

Since Nov 6, 2024.

A-codegen A-enum A-LLVM C-optimization E-needs-test I-heavy I-slow T-compiler
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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.