Skip to content

Pattern matching on Enum.name fails to distinguish between members with duplicate values #127375

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

Closed
1957-001B opened this issue Nov 28, 2024 · 4 comments
Labels
type-bug An unexpected behavior, bug, or error

Comments

@1957-001B
Copy link

1957-001B commented Nov 28, 2024

Bug report

Bug description:

# How to reproduce

from enum import Enum

class Registers(Enum):
    SP = 31   # Stack pointer
    XZR = 31  # Zero register

# Example
for token in ["XZR"]:
    match token:
        case Registers.XZR._name_:
            print("Matched XZR")
        case Registers.SP._name_:
            print("Matched SP")
        case _:
            print("No match")

# Current behavior: Always matches SP case first because SP is defined first
# Expected behavior: Should match XZR case when checking against XZR._name_

The issue appears to be that when pattern matching against _name_ of enum members with duplicate values, Python always matches the first enum member with that value, regardless of which _name_ is being matched against. This makes it impossible to differentiate between enum members with the same value in pattern matching contexts.
This behavior is particularly problematic in cases like ARM assembly parsing where different registers (SP and XZR) share the same value (31) but have distinct semantic meanings and need to be handled differently.

much obliged,

CPython versions tested on:

3.13

Operating systems tested on:

macOS

@1957-001B 1957-001B added the type-bug An unexpected behavior, bug, or error label Nov 28, 2024
1957-001B pushed a commit to 1957-001B/SiliArm that referenced this issue Nov 28, 2024
@TeamSpen210
Copy link

This is because when you give members the same value, they actually get replaced by the same object. The extra name is just an alias - Registers.ZSR is Registers.SP. If you need to distinguish them, you could define the value as ("SP", 31), then define a __new__ which copies the number to another attribute.

@1957-001B
Copy link
Author

Thanks that is super helpful! Is this a deliberate feature of enums or is it a limitation?

@TeamSpen210
Copy link

It's deliberate behaviour yes. You can call an enum class with a value to lookup the corresponding member - Registers(18). If they weren't the same object it'd be ambiguous as to what was returned. Flag enum behaviour would also be very weird, since there you can do bitwise ops to combine/split values.

@1957-001B
Copy link
Author

Ah I see of course - a nice feature indeed. Thank you again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type-bug An unexpected behavior, bug, or error
Projects
None yet
Development

No branches or pull requests

2 participants