[ty] Infer definite equality comparison results#26290
Conversation
Typing conformance resultsNo changes detected ✅Current numbersThe percentage of diagnostics emitted that were expected errors held steady at 94.37%. The percentage of expected errors that received a diagnostic held steady at 89.00%. The number of fully passing files held steady at 94/134. |
Memory usage reportSummary
Significant changesClick to expand detailed breakdownprefect
sphinx
trio
flake8
|
|
| Lint rule | Added | Removed | Changed |
|---|---|---|---|
invalid-argument-type |
0 | 16 | 0 |
invalid-key |
0 | 7 | 0 |
unresolved-attribute |
0 | 5 | 0 |
invalid-assignment |
0 | 2 | 0 |
invalid-return-type |
0 | 1 | 0 |
possibly-unresolved-reference |
0 | 1 | 0 |
unsupported-operator |
0 | 1 | 0 |
| Total | 0 | 33 | 0 |
Flaky changes detected. This PR summary excludes flaky changes; see the HTML report for details.
Raw diff (33 changes)
cloud-init (https://github.com/canonical/cloud-init)
- tests/unittests/distros/test_opensuse.py:287:16 error[unresolved-attribute] Object of type `Distro` has no attribute `read_only_root`
- tests/unittests/distros/test_opensuse.py:308:16 error[unresolved-attribute] Object of type `Distro` has no attribute `read_only_root`
- tests/unittests/distros/test_opensuse.py:329:16 error[unresolved-attribute] Object of type `Distro` has no attribute `read_only_root`
discord.py (https://github.com/Rapptz/discord.py)
- discord/audit_logs.py:210:12 error[invalid-return-type] Return type does not match returned value: expected `list[tuple[Object, PermissionOverwrite]]`, found `list[tuple[Role | Member | User | Object, PermissionOverwrite]]`
freqtrade (https://github.com/freqtrade/freqtrade)
- freqtrade/rpc/telegram.py:579:59 error[invalid-key] Unknown key "status" for TypedDict `RPCAnalyzedDFMsg` (subscripted object has type `RPCStatusMsg | RPCStrategyMsg | RPCProtectionMsg | ... omitted 5 union elements`)
- freqtrade/rpc/telegram.py:579:59 error[invalid-key] Unknown key "status" for TypedDict `RPCEntryMsg` (subscripted object has type `RPCStatusMsg | RPCStrategyMsg | RPCProtectionMsg | ... omitted 5 union elements`)
- freqtrade/rpc/telegram.py:579:59 error[invalid-key] Unknown key "status" for TypedDict `RPCExitMsg` (subscripted object has type `RPCStatusMsg | RPCStrategyMsg | RPCProtectionMsg | ... omitted 5 union elements`)
- freqtrade/rpc/telegram.py:579:59 error[invalid-key] Unknown key "status" for TypedDict `RPCNewCandleMsg` (subscripted object has type `RPCStatusMsg | RPCStrategyMsg | RPCProtectionMsg | ... omitted 5 union elements`)
- freqtrade/rpc/telegram.py:579:59 error[invalid-key] Unknown key "status" for TypedDict `RPCProtectionMsg` (subscripted object has type `RPCStatusMsg | RPCStrategyMsg | RPCProtectionMsg | ... omitted 5 union elements`)
- freqtrade/rpc/telegram.py:579:59 error[invalid-key] Unknown key "status" for TypedDict `RPCStrategyMsg` (subscripted object has type `RPCStatusMsg | RPCStrategyMsg | RPCProtectionMsg | ... omitted 5 union elements`)
- freqtrade/rpc/telegram.py:579:59 error[invalid-key] Unknown key "status" for TypedDict `RPCWhitelistMsg` (subscripted object has type `RPCStatusMsg | RPCStrategyMsg | RPCProtectionMsg | ... omitted 5 union elements`)
psycopg (https://github.com/psycopg/psycopg)
- tests/test_cursor_common.py:159:24 error[unresolved-attribute] Module `psycopg` has no member `ProgrammingError`
- tests/test_cursor_common_async.py:157:24 error[unresolved-attribute] Module `psycopg` has no member `ProgrammingError`
pycryptodome (https://github.com/Legrandin/pycryptodome)
- lib/Crypto/IO/PKCS8.py:210:33 error[invalid-argument-type] Argument to bound method `DerSequence.decode` is incorrect: Expected `bytes`, found `None`
- lib/Crypto/IO/PKCS8.py:210:45 error[invalid-argument-type] Argument to bound method `DerSequence.decode` is incorrect: Expected `int | None`, found `tuple[Literal[1], Literal[2]]`
- lib/Crypto/IO/PKCS8.py:211:37 error[invalid-argument-type] Argument to bound method `DerObjectId.decode` is incorrect: Expected `bytes`, found `None`
- lib/Crypto/IO/PKCS8.py:216:30 error[invalid-argument-type] Argument to bound method `DerObject.decode` is incorrect: Expected `bytes`, found `None`
- lib/Crypto/IO/PKCS8.py:222:43 error[invalid-argument-type] Argument to bound method `DerObject.decode` is incorrect: Expected `bytes`, found `None`
- lib/Crypto/PublicKey/ECC.py:833:44 error[invalid-argument-type] Argument to bound method `DerObject.decode` is incorrect: Expected `bytes`, found `None`
- lib/Crypto/PublicKey/ECC.py:840:57 error[invalid-argument-type] Argument to bound method `DerObjectId.decode` is incorrect: Expected `bytes`, found `None`
- lib/Crypto/PublicKey/ECC.py:865:62 error[invalid-argument-type] Argument to bound method `DerBitString.decode` is incorrect: Expected `bytes`, found `None`
- lib/Crypto/PublicKey/RSA.py:700:22 error[invalid-argument-type] Method `__getitem__` of type `bound method DerSequence.__getitem__(n: int) -> None` cannot be called with key of type `slice[Literal[1], Literal[6], None]` on object of type `DerSequence`
- lib/Crypto/PublicKey/RSA.py:700:22 error[unsupported-operator] Operator `+` is not supported between objects of type `None` and `list[IntegerBase]`
- lib/Crypto/PublicKey/RSA.py:700:42 error[invalid-argument-type] Argument to `IntegerBase.__init__` is incorrect: Expected `IntegerBase | int`, found `None`
- lib/Crypto/PublicKey/RSA.py:700:58 error[invalid-argument-type] Argument to bound method `IntegerBase.inverse` is incorrect: Expected `IntegerBase | int`, found `None`
scrapy (https://github.com/scrapy/scrapy)
- tests/test_http_response.py:328:35 error[invalid-argument-type] Argument to bound method `Response.follow_all` is incorrect: Expected `Iterable[str | Link]`, found `None`
- tests/test_http_response.py:330:35 error[invalid-argument-type] Argument to bound method `Response.follow_all` is incorrect: Expected `Iterable[str | Link]`, found `Literal[12345]`
- tests/test_http_response.py:332:35 error[invalid-argument-type] Argument to bound method `Response.follow_all` is incorrect: Expected `Iterable[str | Link]`, found `list[None]`
trio (https://github.com/python-trio/trio)
- src/trio/_core/_tests/test_run.py:2440:24 error[invalid-assignment] Object of type `Value[object] | Error` is not assignable to `Outcome[str] | None`
- src/trio/_core/_tests/test_run.py:2457:34 error[invalid-argument-type] Argument to bound method `CoroutineType.send` is incorrect: Expected `Outcome[object]`, found `None`
- src/trio/_core/_tests/test_run.py:2470:24 error[invalid-argument-type] Argument to bound method `CoroutineType.send` is incorrect: Expected `Outcome[object]`, found `None`
werkzeug (https://github.com/pallets/werkzeug)
- tests/test_test.py:150:9 error[invalid-assignment] Invalid subscript assignment with key of type `Literal["test_int"]` and value of type `Literal[1]` on object of type `MultiDict[str, str]`
xarray (https://github.com/pydata/xarray)
- xarray/tests/test_cftime_offsets.py:326:22 warning[possibly-unresolved-reference] Name `expected` used when possibly not defined
Merging this PR will degrade performance by 20.19%
|
| Mode | Benchmark | BASE |
HEAD |
Efficiency | |
|---|---|---|---|---|---|
| ❌ | Simulation | ty_micro[literal_equality_fallthrough_guarded_any] |
131.6 ms | 164.9 ms | -20.19% |
Tip
Investigate this regression with the CodSpeed MCP and your agent.
Comparing charlie/infer-equality-comparison-results (963c3e3) with main (bcd2028)
Footnotes
-
64 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩
|
Ugh, I merged the wrong PR. Undoing, then re-opening. |
Reverts #26290. This was accidentally merged.
Summary
The equality rewrite in #25788 centralized runtime
==and!=reasoning for narrowing and match reachability, but ordinary comparison inference continued to use separate literal and dunder logic. As a result, two disjoint enum domains could narrow correctly while the comparison expression itself remainedbool, keeping an impossible branch reachable.This routes definite equality and inequality truthiness through the shared comparison evaluator before falling back to the existing inference path. Ambiguous comparisons still use normal dunder inference, preserving custom non-boolean return types and the independence of
__eq__and__ne__.This also resolves existing tuple comparison TODOs whose mismatched literal elements are already known to compare unequal. With the behavior provided here, #26270 can remain responsible for avoiding same-enum domain expansion without changing comparison results.