Skip to content

Fix enum Self type in match statements and circular dependency#2675

Closed
yangdanny97 wants to merge 1 commit intofacebook:mainfrom
yangdanny97:export-D95437784
Closed

Fix enum Self type in match statements and circular dependency#2675
yangdanny97 wants to merge 1 commit intofacebook:mainfrom
yangdanny97:export-D95437784

Conversation

@yangdanny97
Copy link
Contributor

Summary:
Fix two related issues with enum pattern matching:

  1. Issues non-exhaustive-match false positive for utility / "self" functions on the enum. #2080 and Fake enum literal type #2604: Type::SelfType was not handled alongside
    Type::ClassType in narrowing, subset checking, and overload expansion.
    This caused false-positive "non-exhaustive match" errors when matching
    on self inside enum methods, and incorrect Literal[A.p] return
    types.

  2. Circular dependency bug: get_enum_members resolved ALL class
    fields (including methods), creating a cycle when called during
    method body analysis of enum methods using match self. Added a
    could_be_enum_member flag to ClassFieldProperties so that
    get_enum_members can skip methods and nested classes without
    resolving their types.

Fixes #2080
Fixes #2604

Differential Revision: D95437784

Summary:
Fix two related issues with enum pattern matching:

1. Issues facebook#2080 and facebook#2604: `Type::SelfType` was not handled alongside
   `Type::ClassType` in narrowing, subset checking, and overload expansion.
   This caused false-positive "non-exhaustive match" errors when matching
   on `self` inside enum methods, and incorrect `Literal[A.p]` return
   types.

2. **Circular dependency bug**: `get_enum_members` resolved ALL class
   fields (including methods), creating a cycle when called during
   method body analysis of enum methods using `match self`. Added a
   `could_be_enum_member` flag to `ClassFieldProperties` so that
   `get_enum_members` can skip methods and nested classes without
   resolving their types.

Fixes facebook#2080
Fixes facebook#2604

Differential Revision: D95437784
@meta-cla meta-cla bot added the cla signed label Mar 5, 2026
@meta-codesync
Copy link

meta-codesync bot commented Mar 5, 2026

@yangdanny97 has exported this pull request. If you are a Meta employee, you can view the originating Diff in D95437784.

@github-actions
Copy link

github-actions bot commented Mar 5, 2026

Diff from mypy_primer, showing the effect of this PR on open source code:

archinstall (https://github.com/archlinux/archinstall)
- ERROR archinstall/lib/hardware.py:25:11-23: Returned type `Literal[CpuVendor._Unknown]` is not assignable to declared return type `Self@CpuVendor` [bad-return]
- ERROR archinstall/lib/models/bootloader.py:34:11-28: Returned type `Literal[Bootloader.NO_BOOTLOADER]` is not assignable to declared return type `Self@Bootloader` [bad-return]
- ERROR archinstall/lib/models/bootloader.py:36:11-22: Returned type `Literal[Bootloader.Systemd]` is not assignable to declared return type `Self@Bootloader` [bad-return]
- ERROR archinstall/lib/models/bootloader.py:38:11-19: Returned type `Literal[Bootloader.Grub]` is not assignable to declared return type `Self@Bootloader` [bad-return]
- ERROR archinstall/lib/models/device.py:728:11-22: Returned type `Literal[PartitionType.Primary]` is not assignable to declared return type `Self@PartitionType` [bad-return]
- ERROR archinstall/lib/models/device.py:731:11-23: Returned type `Literal[PartitionType._Unknown]` is not assignable to declared return type `Self@PartitionType` [bad-return]
- ERROR archinstall/lib/models/users.py:61:13-23: Returned type `Literal[PasswordStrength.STRONG]` is not assignable to declared return type `Self@PasswordStrength` [bad-return]
- ERROR archinstall/lib/models/users.py:63:13-25: Returned type `Literal[PasswordStrength.MODERATE]` is not assignable to declared return type `Self@PasswordStrength` [bad-return]
- ERROR archinstall/lib/models/users.py:65:13-21: Returned type `Literal[PasswordStrength.WEAK]` is not assignable to declared return type `Self@PasswordStrength` [bad-return]
- ERROR archinstall/lib/models/users.py:67:13-26: Returned type `Literal[PasswordStrength.VERY_WEAK]` is not assignable to declared return type `Self@PasswordStrength` [bad-return]
- ERROR archinstall/lib/models/users.py:71:13-23: Returned type `Literal[PasswordStrength.STRONG]` is not assignable to declared return type `Self@PasswordStrength` [bad-return]
- ERROR archinstall/lib/models/users.py:73:13-25: Returned type `Literal[PasswordStrength.MODERATE]` is not assignable to declared return type `Self@PasswordStrength` [bad-return]
- ERROR archinstall/lib/models/users.py:75:13-21: Returned type `Literal[PasswordStrength.WEAK]` is not assignable to declared return type `Self@PasswordStrength` [bad-return]
- ERROR archinstall/lib/models/users.py:77:13-26: Returned type `Literal[PasswordStrength.VERY_WEAK]` is not assignable to declared return type `Self@PasswordStrength` [bad-return]
- ERROR archinstall/lib/models/users.py:81:13-23: Returned type `Literal[PasswordStrength.STRONG]` is not assignable to declared return type `Self@PasswordStrength` [bad-return]
- ERROR archinstall/lib/models/users.py:83:13-25: Returned type `Literal[PasswordStrength.MODERATE]` is not assignable to declared return type `Self@PasswordStrength` [bad-return]
- ERROR archinstall/lib/models/users.py:85:13-21: Returned type `Literal[PasswordStrength.WEAK]` is not assignable to declared return type `Self@PasswordStrength` [bad-return]
- ERROR archinstall/lib/models/users.py:87:13-26: Returned type `Literal[PasswordStrength.VERY_WEAK]` is not assignable to declared return type `Self@PasswordStrength` [bad-return]
- ERROR archinstall/lib/models/users.py:91:13-23: Returned type `Literal[PasswordStrength.STRONG]` is not assignable to declared return type `Self@PasswordStrength` [bad-return]
- ERROR archinstall/lib/models/users.py:93:13-25: Returned type `Literal[PasswordStrength.MODERATE]` is not assignable to declared return type `Self@PasswordStrength` [bad-return]
- ERROR archinstall/lib/models/users.py:95:13-21: Returned type `Literal[PasswordStrength.WEAK]` is not assignable to declared return type `Self@PasswordStrength` [bad-return]
- ERROR archinstall/lib/models/users.py:97:13-26: Returned type `Literal[PasswordStrength.VERY_WEAK]` is not assignable to declared return type `Self@PasswordStrength` [bad-return]
- ERROR archinstall/lib/models/users.py:99:10-23: Returned type `Literal[PasswordStrength.VERY_WEAK]` is not assignable to declared return type `Self@PasswordStrength` [bad-return]

mitmproxy (https://github.com/mitmproxy/mitmproxy)
- ERROR mitmproxy/proxy/layers/http/_events.py:127:37-42: Argument `Self@ErrorCode` is not assignable to parameter `arg` with type `Never` in function `typing.assert_never` [bad-argument-type]

jax (https://github.com/google/jax)
+  WARN jax/_src/pallas/mosaic/tpu_info.py:92:16-63: Redundant cast: `int` is the same type as `int` [redundant-cast]

@github-actions
Copy link

github-actions bot commented Mar 5, 2026

Primer Diff Classification

✅ 3 improvement(s) | 3 project(s) total

3 improvement(s) across archinstall, mitmproxy, jax.

Project Verdict Changes Error Kinds Root Cause
archinstall ✅ Improvement -23 bad-return pyrefly/lib/alt/narrow.rs
mitmproxy ✅ Improvement -1 bad-argument-type pyrefly/lib/alt/narrow.rs
jax ✅ Improvement +1 redundant-cast _num_physical_tensor_cores_per_chip()
Detailed analysis

✅ Improvement (3)

archinstall (-23)

These were false positive errors that have been correctly fixed. The code shows standard enum patterns where classmethods return specific enum members with -> Self annotations. Looking at the specific examples:

  1. In CpuVendor.get_vendor() (line 25): return cls._Unknown where _Unknown is a valid enum member and cls is the enum class. This satisfies -> Self.

  2. In Bootloader.get_default() (line 34): return cls.NO_BOOTLOADER where NO_BOOTLOADER is a valid enum member.

The PR description explains this was issue #2604 where Type::SelfType wasn't handled alongside Type::ClassType in narrowing and subset checking. The fix correctly treats Self in enum contexts as equivalent to the enum class type, so Literal[EnumClass.member] is properly recognized as compatible with Self@EnumClass. This is an improvement - pyrefly now correctly understands enum method return types instead of producing false positive bad-return errors.

Attribution: The changes to pyrefly/lib/alt/narrow.rs, pyrefly/lib/alt/overload.rs, and pyrefly/lib/solver/subset.rs added handling for Type::SelfType alongside Type::ClassType in pattern matching, overload expansion, and subset checking. This fixed the type system's understanding that Self in enum methods should be treated equivalently to the enum class type for narrowing and compatibility checks.

mitmproxy (-1)

This removal is an improvement. The error was a false positive caused by pyrefly's failure to properly narrow Self types in enum match statements. The match statement covers all 13 ErrorCode enum members explicitly, making the case other: branch genuinely unreachable. Per the typing spec on narrowing, other should have type Never in an exhaustive match, which is exactly what typing.assert_never() expects. The PR fixed the type narrowing logic to handle Type::SelfType properly, resolving this false positive.
Attribution: The changes to narrowing logic in pyrefly/lib/alt/narrow.rs, subset checking in pyrefly/lib/solver/subset.rs, and overload expansion in pyrefly/lib/alt/overload.rs added handling for Type::SelfType alongside Type::ClassType. This fixed the Self type narrowing in enum match statements.

jax (+1)

This is an improvement. The PR fixed pyrefly's ability to infer return types from enum methods that use match self. Previously, pyrefly couldn't handle Type::SelfType in enum pattern matching, so _num_physical_tensor_cores_per_chip() had an incorrect inferred return type, requiring a cast(int, ...) workaround. Now pyrefly correctly infers the method returns int, making the cast redundant. The error correctly identifies unnecessary code that can be removed - this is exactly what redundant-cast warnings should catch.
Attribution: The enum self-type fixes in pyrefly/lib/alt/narrow.rs, pyrefly/lib/alt/overload.rs, and pyrefly/lib/solver/subset.rs that added Type::SelfType handling alongside Type::ClassType enabled pyrefly to correctly infer the return type of _num_physical_tensor_cores_per_chip(), making the cast redundant.


Was this helpful? React with 👍 or 👎

Classification by primer-classifier (3 LLM)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fake enum literal type non-exhaustive-match false positive for utility / "self" functions on the enum.

1 participant