[ty] Optimize enum comparisons in equality evaluation#26340
Merged
Conversation
Typing conformance resultsNo changes detected ✅Current numbersThe percentage of diagnostics emitted that were expected errors held steady at 94.47%. The percentage of expected errors that received a diagnostic held steady at 89.19%. The number of fully passing files held steady at 95/134. |
Memory usage reportSummary
Significant changesClick to expand detailed breakdownprefect
trio
sphinx
|
|
| Lint rule | Added | Removed | Changed |
|---|---|---|---|
invalid-argument-type |
0 | 1 | 0 |
| Total | 0 | 1 | 0 |
Raw diff:
rotki (https://github.com/rotki/rotki)
- rotkehlchen/api/services/transactions.py:792:40 error[invalid-argument-type] Argument to bound method `list.extend` is incorrect: Expected `Iterable[Literal[SupportedBlockchain.ETHEREUM, SupportedBlockchain.OPTIMISM, SupportedBlockchain.POLYGON_POS, SupportedBlockchain.ARBITRUM_ONE, SupportedBlockchain.BASE, ... omitted 6 literals]]`, found `list[SupportedBlockchain]`aa2f03a to
3a15517
Compare
3a15517 to
e8bf30e
Compare
carljm
approved these changes
Jun 25, 2026
carljm
left a comment
Contributor
There was a problem hiding this comment.
Great results, both semantic and perf!
I admit I did not read the entire new 900-line enum-compare implementation line-by-line. I did interrogate Codex about the key abstractions in it, and they make sense to me. I did read the mdtests.
Comment on lines
+202
to
+206
| class CoercingAlias(str, Enum): | ||
| FIRST = 1 | ||
| SECOND = "1" | ||
|
|
||
| reveal_type(CoercingAlias.FIRST == CoercingAlias.SECOND) # revealed: bool |
Contributor
There was a problem hiding this comment.
Codex points out that this somewhat similar case regresses in precision from main to this PR:
from enum import IntEnum
class E(IntEnum):
ZERO = 0
FALSE = False
reveal_type(E.ZERO == E.FALSE) # Literal[True] on main, bool hereOTOH I think maybe this is fine; OTOH modeling that False is 0 does feel a little more "core" than modeling that str("1") is 1, and might not be hard?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Since #25955 and #26337, equality narrowing, match reachability, membership compatibility, and ordinary
==and!=result inference all use the same comparison evaluator, within which comparing large enums ends up performing a large member cross-product operation.This PR adds a fast path for enums, whereby same-class operands use compact member sets and cross-class / multi-class unions project members onto cached runtime comparison keys. The cache is per enum class and comparison operator, so repeated comparisons reuse the class-wide scan instead of repeating it for every type pair or expression. Because it's in the shared evaluator, this optimization applies consistently to equality and inequality narrowing, definite comparison results and resulting reachability, value-pattern narrowing, and membership compatibility.
(Note:
SameEnumComparisonis a fast path within the fast path for enums of the same class. Within the same class, we can just compare member-name sets; for different classes, we need project down to a value.)In quick local benchmarks against current
main, the original astral-sh/ty#3830 reproducer drops from roughly 14.4 s to 9.3 ms, a comparison between two 256-memberStrEnums drops from roughly 242 ms to 10.8 ms, and a comparison between unions spanning 16 enum classes drops from roughly 296 ms to 10.9 ms.Closes astral-sh/ty#3830.